C# 3.0 LINQの続きです。
ラムダ式でも、{}で囲んで、複文(とC#でも言うのかな?)を形成できるようです。これを知らず、前回は匿名デリゲートを使っていました。
あと、null許容型を使うというアイデアを思い付いて、結果こうなりました。
var fizzbuzz = Enumerable.Range(1, 20).Select( i => { string s; if (i % 5 == 0) s = "fizz"; else s = null; if (i % 3 == 0) s += "buzz"; return s ?? i.ToString(); }); foreach (var s in fizzbuzz) { Console.WriteLine(s); } |
全く別のアプローチで、こんなのもどうでしょう。foreachが使えないのが痛いですけど。
var r = Enumerable.Range(1, 20); var notFizzBuzz = from p in r select p % 3 != 0 && p % 5 != 0 ? p.ToString() : ""; var fizz = from p in r select p % 3 == 0 ? "Fizz" : ""; var buzz = from p in r select p % 5 == 0 ? "Buzz" : ""; using (var en = notFizzBuzz.GetEnumerator()) using (var ef = fizz.GetEnumerator()) using (var eb = buzz.GetEnumerator()) { while (en.MoveNext()) { ef.MoveNext(); eb.MoveNext(); Console.Write(en.Current); Console.Write(ef.Current); Console.Write(eb.Current); Console.WriteLine(); } } |
まだ試行錯誤は続きます。
Selectには要素数を2つ目の引数に取るラムダ式も受け付けるとのことで、こんなものも作ってみました。0から始まるのはご愛嬌。
var fizzbuzz = Enumerable.Repeat<object>(null, 21) .Select((o, i) => i % 15 == 0 ? "FizzBuzz" : null) .Select((s, i) => s ?? (i % 5 == 0 ? "Fizz" : null)) .Select((s, i) => s ?? (i % 3 == 0 ? "Buzz" : null)) .Select((s, i) => s ?? i.ToString()); |
var fizzbuzz = Enumerable.Repeat<object>(null, 21) .Select((s, i) => (i % 5 == 0 ? "Fizz" : null)) .Select((s, i) => s + (i % 3 == 0 ? "Buzz" : null)) .Select((s, i) => string.IsNullOrEmpty(s) ? i.ToString() : s); |
下のコードで、string.IsNullOrEmpty(s) ? i.ToString() : sとしているのは、上の行で(string)null + (string)nullの結果が空文字列(長さ0の文字列)となるためです。詳しくは後日。最初はs ?? i.ToString()と書いていました。
暇ではないのに、暇潰しをさせてくれるとは、中々やってくれますね。LINQには、C++ STLのような世界の広さを感じます。
スポンサード リンク |
この記事のカテゴリ
- C# ⇒ 呪文FizzBuzz