【C#】LINQのGroupByの使い方、KeyとValueの取得方法

グループ化とはなにか

グループ化とは、ある”特徴”をもとに、いくつかのグループに分ける作業のことを言います。

例えば、小学校のクラスで「運動が得意な子」と「運動が得意でない子」の2つに分けることもグループ化と言えるでしょう。

LINQのGroupByを用いたグループ化

名前、性別、出身の3つの要素を持つ匿名クラスの配列を用意しました。1つめの要素なら、「Aさん、男性、東京出身」となります。

var people = new[] { new { Name = "A", Gender = "M", Age = 10, City = "Tokyo"},
                     new { Name = "B", Gender = "W", Age = 86, City = "Osaka"},
                     new { Name = "C", Gender = "M", Age = 26, City = "Fukuoka"},
                     new { Name = "D", Gender = "W", Age = 32, City = "Tokyo"},
                     new { Name = "E", Gender = "M", Age = 13, City = "Osaka"},
                     new { Name = "F", Gender = "M", Age = 24, City = "Tokyo"},
                     new { Name = "G", Gender = "W", Age = 59, City = "Tokyo"},
                     new { Name = "H", Gender = "M", Age = 18, City = "Osaka"},
                     new { Name = "I", Gender = "M", Age = 62, City = "Tokyo"},
                     new { Name = "J", Gender = "W", Age = 33, City = "Fukuoka"} };

まずは、このAさん~Jさんの10名を、”出身”ごとに分類します。LINQを使ってグループ化を行うには、ラムダ式を用いて、以下のように書きます。

// Cityでグループ化
var groupByCity = people.GroupBy(x => x.City);

これで、Tokyo・Osaka・Fukuokaの都市ごとにグループ化がされます。

グループ化のイメージ

キーとバリューの取り出し方

次は、グループのキーと、それに属する値(バリュー)の取得方法についてです。
図で見れば「Tokyo」というグループにAさん、Dさん、Fさん、Gさん、Iさんが属しているのがわかりますが、「Tokyo」というキーと、人の名前を取得するにはどうすればいいのでしょうか?

最もわかりやすい書き方だと、グループをforeachで回し、以下のようにキーとバリューを取得する方法です。

5行目でキーを表示しています。IGrouping型は.Keyプロパティを用いることでキーを取得できます。

8行目でキーに属する人の名前のリストを作成しています。IGrouping型に対してSelectメソッドを用いることによって、キーに属するバリューを取得できます。

// foreachでKeyごとに繰り返し
foreach(var city in groupByCity)
{
    // グループのキーを表示
    Console.WriteLine(city.Key);

    // キーに属するバリューをリスト化
    var nameList = city.Select(x => x.Name).ToList();
    foreach(var name in nameList)
    {
        Console.WriteLine(name + "さん");
    }
}

/*
Tokyo
Aさん
Dさん
Fさん
Gさん
Iさん
Osaka
Bさん
Eさん
Hさん
Fukuoka
Cさん
Jさん
*/

別にForeachに拘る必要はありません。以下のようにLINQのSelectを用いた書き方でもデータを扱うことが可能です。以下のサンプルだと、{キー , 名前のリスト}という形で配列を取得しています。

// LINQを用いてリストにしてもOK
var keyAndValues = groupByCity.Select(x => new { Key = x.Key, Names = x.Select(y => y.Name).ToList() }).ToList();

条件でグループ化する

「出身地が同じ」というようなイコールによるグループ化だけでなく、「X歳以上」というような、比較演算子を用いた条件でグループ化することが可能です。

以下の例では、50歳以下と50歳以上でグループ化しています。このとき注意すべきなのが、キー名がTrueとFalseになることです。50歳以下のグループに対してTrueのキーが割り当てられているのがわかります。

// Ageでグループ化(条件でグループ化)
var groupByAge = people.GroupBy(x => x.Age < 50);

foreach (var age in groupByAge)
{
    Console.WriteLine("50歳" + (age.Key ? "以下" : "以上"));
    
    var nameList = age.Select(x => x.Name).ToList();
    foreach (var name in nameList)
    {
        Console.WriteLine(name + "さん");
    }
}

 /*
 50歳以下
 Aさん
 Cさん
 Dさん
 Eさん
 Fさん
 Hさん
 Jさん
 50歳以上
 Bさん
 Gさん
 Iさん
 */

複数のキーでグループ化する

今までは一つのキーでグループ化をしてきましたが、「男性かつ東京出身」のように、複数のキーでグループ化をすることもできます。

以下の例では、性別と出身地の2つのキーでグループ化を行っています。ポイントは、2行目の「キーを匿名クラスで作成する」という点です。

 //複数のキーでグループ化
var groupBySomeKeys = people.GroupBy(x => new { x.Gender, x.City });

foreach (var group in groupBySomeKeys)
{
    Console.WriteLine(group.Key);
    foreach(var person in group)
    {
        Console.WriteLine(person.Name + "さん");
    }
    
}

/*
 { Gender = M, City = Tokyo }
 Aさん
 Fさん
 Iさん
 { Gender = W, City = Osaka }
 Bさん
 { Gender = M, City = Fukuoka }
 Cさん
 { Gender = W, City = Tokyo }
 Dさん
 Gさん
 { Gender = M, City = Osaka }
 Eさん
 Hさん
 { Gender = W, City = Fukuoka }
 Jさん
 */

コメント

タイトルとURLをコピーしました