2015年1月12日月曜日

Enumerable.GroupByメソッドの威力

2015年も明けて間もなく2週間が経とうとしています。

おそくなりましたが、今年もよろしくお願いします。

今年の目標は「去年のエントリ数を超える」こと。2014年は5本だったようなので、達成できそうな目標にしてみました。

一発目のエントリは、「GroupBy」をテーマにしてみます。非常に強力なLINQのメソッドですが、なかなか使う機会が少ない人も多いのではないかと思います。

「GroupBy」メソッドは、SQLを触ったことのある人なら「group by」句をイメージしてもらうとほぼ間違いなしで、つまりは「コレクション内の各要素を、ある条件でグループ分けする」メソッドです。ぱっと見面倒そうですが、使い方はいたってシンプルです。

サンプルを書いてみましょう。

  • データメンバとして、日付(Date)と売上額(Amount)を持つSalesクラスがあります。
  • Salesクラスは、ある指定期間の日別の売上額を列挙するEnumerate静的メソッドを持ちます。
  • ここで、上記Salesクラスを使い、ある年(ここでは2014年)の曜日別の売り上げの総合計、平均値、中間値を算出します。
この処理は以下のコードになります。

static void ShowGroupedAmounts()
{
  var from = new DateTime(2014, 1, 1);
  var to = new DateTime(2014, 12, 31);
  var group = Sales.Enumerate(from, to)
    .GroupBy(s => s.Date.DayOfWeek)
    .OrderBy(g => g.Key);

  Console.WriteLine("DayOfWeak,Total Amount,Average,Median");

  foreach (var g in group)
  {
    var cnt = g.Count();

    Console.WriteLine(
      "{0},{1},{2},{3}",
      g.Key,
      g.Sum(s => s.Amount),
      Math.Round(g.Average(s => s.Amount), 1),
      g.OrderBy(s => s.Amount).Skip(cnt / 2).First().Amount);
  }
}

非常にシンプルなコードで、キー(ここでは曜日)ごとにグループ化できていると思います。なお、GroupByメソッドの戻り値は以下の形態になります。

IEnumerable<IGrouping<DayOfWeak, Sales>>

IGroupingは、IEnumerable<T>にキー情報を加えたもの。と考えればOKです。

0 件のコメント:

コメントを投稿