2015年07月19日

LINQ to Objectサンプル(21): 条件を満たしている間の値を取り出す

  
今回は、整数の二乗の桁数が 3 桁 である 整数を求めたいと思います。

例えば、 8 * 8 は、 64 で条件を満たしません。12 * 12 は 144 で条件を満たします。


■ループを使ったコード
List<int> list = new List<int>();
int n = 1;
string s = (n * n).ToString();
while (s.Length < 4) {
    if (s.Length == 3)
        list.Add(n);
    n++;
    s = (n * n).ToString();
}
foreach (var num in list) {
    Console.WriteLine("{0} * {0} = {1}", num, num * num);
}


今までのコードと決定的に違うのは、何回ループさせたらよいか分からないという点ですね。

3桁になったら、リストの格納を開始し、4桁になったらループから抜け出しています。


では、LINQを使って書いてみます。ちょっと発想を変えていますが、結果は同じです。
■LINQを使ったコード
var seq = Enumerable.Range(1, int.MaxValue)
                     .SkipWhile(n => (n * n).ToString().Length < 3)
                     .TakeWhile(n => (n * n).ToString().Length == 3);
seq.ToList().ForEach(n => Console.WriteLine("{0} * {0} = {1}", n, n * n));


Enumerable.Rangeメソッドを使うと、指定した範囲の整数を順に列挙することができます。
最大値がわからないので、ここでは、int.MaxValueの数だけ整数を列挙しています。
100*100 は明らかに、4桁をオーバーするので、

Enumerable.Range(1, 100)

としてもかまいませんが、100の根拠が不明瞭ですし、どちらにせよ速度は変わりないです。

SkipWhileメソッドで、二乗が3桁未満の整数をスキップします。
TakeWhileメソッドで、二乗が3桁の間だけ値を取り出しています。
if文を書かずに、こういった処理が書けるのも LINQの楽しいところです。

上の例では、いったん文字列にして桁数を判断していますが、整数のまま処理することもできますね。 以下がそのコードです。


var seq = Enumerable.Range(1, int.MaxValue)
                     .SkipWhile(n => (n * n) < 100)
                     .TakeWhile(n => (n * n) < 1000);
seq.ToList().ForEach(n => Console.WriteLine("{0} {1}", n, n * n));



 

この記事へのトラックバックURL

http://trackback.blogsys.jp/livedoor/gushwell/52426779