グループ化とはなにか
グループ化とは、ある”特徴”をもとに、いくつかのグループに分ける作業のことを言います。
例えば、小学校のクラスで「運動が得意な子」と「運動が得意でない子」の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さん
*/
コメント