自作クラスのリストから重複を取り除きたい
C#にはLinqのDistinctメソッドがある。
これはstring型やint型のリストには有効だが、そのままだと自作クラスでは機能しない。
IEnumerableを実装したクラスまたはIEqualityComparerの実装を作りDistinctメソッドで回すことが定石だが、もっと簡単な方法があったのでメモ φ(・・
string型やint型のリストにはDistinctでOK
var array1 = new string[] { "a", "a", "b", "b" };
foreach (var x in array1.Distinct())
Console.Write(x);
// ab *OK
自作クラスのとき
2021/01/06: コメントを受けて修正済み
var source = new List<M>
{
new M { P1 = "a", P2 = "a" },
new M { P1 = "a", P2 = "a" },
new M { P1 = "b", P2 = "b" },
new M { P1 = "b", P2 = "c" }
};
var array2 = source.Distinct();
foreach (var x in array2)
Console.Write($"{{P1: {x.P1}, P2: {x.P2}}}");
// {P1: a, P2: a}{P1: a, P2: a}{P1: b, P2: b}{P1: b, P2: c}
// {P1: a, P2: a} の重複が取り除かれていない
var array3 = source
.GroupBy(x => new { x.P1, x.P2 })
.Select(x => x.First());
foreach (var x in array3)
Console.Write($"{{P1: {x.P1}, P2: {x.P2}}}");
// {P1: a, P2: a}{P1: b, P2: b}{P1: b, P2: c}
// *OK
追記(2021/01/06)
@albireo さんにもっとシンプルな方法で教えてもらいました。
C#7.3からはタプル同士を ==
!=
演算子で比較できるようになったそうです。
サンプルコードはコメントを参照してください。
コメントからの抜粋ですが、
GroupByを使わないと難しいのは、「重複チェックでは対象外のプロパティも重複除外後に参照したい場合」
とのことです