ソフラボの技術ブログ

仕事で使ったプログラミング、サーバー周りで役に立つこと、Webサービス開発に必要な技術情報、モバイル情報を書いてます。わかりやすく見やすくをモットーにしています。

LINQでグルーピングした最大の要素を取得する

C#でグルーピングして最大の要素を取得したかったので、試行錯誤して調べた結果、MaxではなくOrderByDescendingを使うことで実現できました。

まだまだLINQは、使い慣れてないのでちょっと特殊なことをしようとするとハマって時間が取られてしまいました…。そんなんでお困りの方、ご参考に。

少し解説すると、以下のようになります。
GroupBy
・第1引数:元の値を何でグループ化するかを指定する
・第2引数:元の値をグループ化したものに対して、キーと値の2つの引数が使え、値に対しての処理を指定する

OrderByDescending
元の値を第1引数で指定したもので昇順に並べ、Firstを指定することで先頭を取得する

サンプルコード

// 値を持つクラス
public class Hoge
{
    public int Key { get; set; }

    public string Dt { get; set; }
}

// グルーピングして最大を取得する処理
public void Main(string[] args)
{
    // 値の設定
    List<Hoge> list = new List<Hoge> {
	new Hoge() { Key = 1, Dt = "20190101" },
	new Hoge() { Key = 1, Dt = "20190102" },
	new Hoge() { Key = 2, Dt = "20190101" },
	new Hoge() { Key = 3, Dt = "20190310" },
	new Hoge() { Key = 3, Dt = "20190305" },
	new Hoge() { Key = 3, Dt = "20190301" },
	new Hoge() { Key = 4, Dt = "20190101" },
	new Hoge() { Key = 4, Dt = "20190102" },
	new Hoge() { Key = 5, Dt = "20190103" },
    };

    // Key毎にDtが最大の要素を取得
    List<Hoge> retList = list
	.GroupBy(
	    h => h.Key,
	    (k, v) => v.OrderByDescending(o => o.Dt).First())
	.ToList();

    // 結果
    retList.ForEach(f => Console.WriteLine("{0} {1}", f.Key, f.Dt));
}

結果

1 20190102
2 20190101
3 20190310
4 20190102
5 20190103

Key毎にDtが最大の要素がListに格納されています。