【C#/LINQ】LINQの学習 その(3) 集計する

投稿者: | 2011年12月24日

今回は値のシーケンスに対して合計したり、平均を求めたりするメソッドについて見ていく。
サンプルとして、以下のようなシーケンスを用意した。

var persons = new[]
{
	new{Name="Tom",Age=17},
	new{Name="Ken",Age=46},
	new{Name="Alice",Age=18},
	new{Name="Mike",Age=19},
	new{Name="John",Age=23},
	new{Name="Chris",Age=37},
	new{Name="Bob",Age=35},
};

まずはAggregateである。このメソッドを使い、サンプルのAgeの合計を求めるには以下のように書く。

persons.Aggregate(0, (c, p) => c + p.Age);
// 実行結果は「195」

Aggrigateの第1引数には集計の初期値を指定する。ここでは0を指定している。
第2引数はSystem.Func<TAccumulate, TSource, TAccumulate>型のデリゲートである。
記号で書くと少し分かりにくいが、引数として、これまでの集計値(TAccumulate)、集計元となるデータ(TSource)をとり、新しい集計値(TAccumulate)を返す、という意味である。
もし、デリゲートの定義だけを見て動きがイメージしにくいようであれば、試しに引数の値やラムダの返り値を変えてみると分かりやすくなるのではないだろうか・・・。
例えば、

persons.Aggregate(20, (c, p) => c);

と書いてみよう。このように書けば、初期値は20で、ラムダでは集計結果は何も加工せずにそのままの値を返しているだけなので、実行結果は「20」となるはずである。

さて、合計を求めるだけならばもっと簡単にできるメソッドが用意されている。それはSumメソッドである。
このメソッドを使い、サンプルのAgeの合計を求めるには以下のように書く。

persons.Sum(p=>p.Age);
// 実行結果は「195」

同じ事をしたいのであれば、より簡単なやり方を選んだ方が良いだろう。

最後に、平均を求めるAverageメソッドを紹介する。
サンプルのAgeの平均を求めてみよう。

persons.Average(p => p.Age);
// 実行結果は「27.8571428571429」

昔は、同じようなことをするためにはfor文を使ったり、変数を用意したりする必要があり、
初心者向けの題材としてもよく取り上げられたりしていたものだが、今はメソッド一つ呼び出すだけで
実現できてしまうということである。ループの構文が必要な場面は減ってきている。
(ただし、より抽象的に考える必要があり、慣れないとややこしいとも言える。)

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です