C# 3.0 と let キーワード
そういえば C# 3.0 にも let キーワードがあったなぁと思いだし let 書きたくなる病.
FizzBuzz
例えば id:siokoshou:20070714:p1 で書いた FizzBuzz で無理矢理 let を使ってみる.
var f1 = Enumerable.Range(1, 100).Select( n => { if (0 == n % 15) return "FizzBuzz"; if (0 == n % 5) return "Buzz"; if (0 == n % 3) return "Fizz"; return n.ToString(); }); var f2 = from x in Enumerable.Range(1, 100) let a = x % 3 == 0 ? "Fizz" : "" let b = x % 5 == 0 ? "Buzz" : "" let c = (x % 3 != 0 && x % 5 != 0) ? x.ToString() : "" select a + b + c; var check = Enumerable.SequenceEqual(f1, f2); Console.WriteLine("f1 == f2 : {0}", check);
まあこれぐらいだとあんまり意味なさげ.
今年の1月1日から12月31日までを列挙
let が欲しくなるのは例えばこういうクエリかな.
var cal = from month in Enumerable.Range(1, 12) let year = DateTime.Today.Year let numDays = DateTime.DaysInMonth(year, month) from day in Enumerable.Range(1, numDays) select new DateTime(year, month, day);
2000年から2009年までの13日の金曜日は?
ちょっとそれらしい問題にしてみました.
var ft13 = from year in Enumerable.Range(2000, 10) let daysInThisYear = from month in Enumerable.Range(1, 12) let numDays = DateTime.DaysInMonth(year, month) from day in Enumerable.Range(1, numDays) select new DateTime(year, month, day) from date in daysInThisYear where date.Day == 13 && date.DayOfWeek == DayOfWeek.Friday select date; foreach (var item in ft13) { Console.WriteLine("{0}/{1}/{2}", item.Year, item.Month, item.Day); }
まあひとつきの日数が13より少ないことはないので,いったん日にちまで列挙するのは余計なんですが,それがまたわざとらしい.
2000/10/13
2001/4/13
2001/7/13
2002/9/13
2002/12/13
2003/6/13
2004/2/13
2004/8/13
2005/5/13
2006/1/13
2006/10/13
2007/4/13
2007/7/13
2008/6/13
2009/2/13
2009/3/13
2009/11/13
2000年から2009年までの各年の日曜日の数
無理矢理ひとつのクエリで書いてみました.
var mysundays = from year in Enumerable.Range(2000, 10) let daysInThisYear = from month in Enumerable.Range(1, 12) let numDays = DateTime.DaysInMonth(year, month) from day in Enumerable.Range(1, numDays) select new DateTime(year, month, day) let sundaysInThisYear = from date in daysInThisYear where date.DayOfWeek == DayOfWeek.Sunday select date select new { Year = year, SundayCount = sundaysInThisYear.Count() }; foreach (var item in mysundays) { Console.WriteLine("{0} => {1}", item.Year, item.SundayCount ); }
んー,さすがにこれぐらいになると関数定義してもよさげ.
Func<int, IEnumerable<DateTime>> daysInYear = year => from month in Enumerable.Range(1, 12) let numDays = DateTime.DaysInMonth(year, month) from day in Enumerable.Range(1, numDays) select new DateTime(year, month, day); var mysundays = from year in Enumerable.Range(2000, 10) let sundays = from date in daysInYear(year) where date.DayOfWeek == DayOfWeek.Sunday select date select new { Year = year, SundayCount = sundays.Count() }; foreach (var item in mysundays) { Console.WriteLine("{0} => {1}", item.Year, item.SundayCount ); }
2000 => 53
2001 => 52
2002 => 52
2003 => 52
2004 => 52
2005 => 52
2006 => 53
2007 => 52
2008 => 52
2009 => 52