GroupByで配列を含む複数のキーから要素をグループ化できるようにする
概要
例えば、以下のようなデータがあります。
class Book { public int Id { get; set; } public int CityId { get; set; } public int[] ReferenceIds { get; set; } } var data = new List<Book>() { new Book { Id = 1, CityId = 1, ReferenceIds = new int[]{ 1 } }, new Book { Id = 2, CityId = 1, ReferenceIds = new int[]{ 1 } }, new Book { Id = 3, CityId = 1, ReferenceIds = new int[]{ 9, 1 } }, new Book { Id = 4, CityId = 2, ReferenceIds = new int[]{ 1 } }, new Book { Id = 5, CityId = 1, ReferenceIds = new int[]{ 5 } }, };
ここから、LINQのGroupBy()
を用いてReferenceIds
の配列数と中身の値が全て同一、かつCityId
が同じ場合は1つのグループとにまとめたい状況を考えます。
(上のコードだと、Idが1と2のクラスは1つにまとまり、それ以外のデータは別々のグループになるようにしたい)
このグループ化は、デフォルトで用意されている複数キーを使ったGroupByだと上手くまとまらなかったので、 IEqualityComparer
を用いてグループ化の条件を自作します。
サンプルコード
今回はTupleを利用して複数のキーをまとめて1つのキーとみなし、IEqualityComparerを継承した等値比較クラスで判定します。
実行結果
■Group CityId:1, RefIdsLen:1 ┗Id:1, CityId:1, RefIdsLen:1, RefIds:1 ┗Id:2, CityId:1, RefIdsLen:1, RefIds:1 ■Group CityId:1, RefIdsLen:2 ┗Id:3, CityId:1, RefIdsLen:2, RefIds:9, 1 ■Group CityId:2, RefIdsLen:1 ┗Id:4, CityId:2, RefIdsLen:1, RefIds:1 ■Group CityId:1, RefIdsLen:1 ┗Id:5, CityId:1, RefIdsLen:1, RefIds:5
CityId
の値とReferenceIds
が同じものでグループ化されているのが確認できました。
おまけ
雑にやっていいならIEqualityComparer
を利用せずReferenceIds
とCityId
をString化して直接連結する方法でも実現可能。
var groupedDataList = data.GroupBy(d => string.Join(",", d.ReferenceIds.Append(d.CityId))).ToArray();