web-dev-qa-db-ja.com

リスト内の重複オブジェクトの削除(C#)

したがって、LinqのDistinct()を使用して、文字列やintなどに関してリスト内の重複を削除する方法を理解しています。しかし、オブジェクトの特定の属性に基づいて重複をどのように削除しますか?

たとえば、私はTimeMetricクラスを持っています。このTimeMetricクラスには、MetricTextMetricTimeの2つの属性があります。 TimeMetricsというMetricListのリストがあります。同じTimeMetric属性を持つ重複するMetricTextを削除したい。 TimeMetricの値は同じでもかまいませんが、TimeMetricMetricTextが同じである場合は、複製を解除する必要があります。

18
Jay

IEqualityComparer<TimeMetric> インスタンスを2番目のパラメーターとして受け取るDistinctの2番目のオーバーロードを使用する必要があります。次のように比較子を定義します。

class MyComparer : IEqualityComparer<TimeMetric>
{
    public bool Equals(TimeMetric x, TimeMetric y)
    {
        return x.MetricText.Equals(y.MetricText);
    }

    public int GetHashCode(TimeMetric obj)
    {
        return obj.MetricText.GetHashCode();
    }
}

重要な注意:上記のコードは、MetricTextプロパティがnullである場合をチェックしません(そしてそれは聞こえます)おそらくstring)なので、そうなる可能性があります。 GetHashCodeMetricTextの場合は、それを実行してnullから0を返す必要があります。一方、MetricTextの型が値型の場合は、変更を加える必要はありません。

その後:

var list = new List<TimeMetric> { ... };
var unique = list.Distinct(new MyComparer());
21
Jon

Linqを使用する:

var list = list 
    .GroupBy(i => i.MetricText)
    .Select(g => g.First())
    .ToList();

または、プロパティを使用する比較子を渡します。

public class mtCompare : IEqualityComparer<TimeMetric>
{
  public bool Equals(TimeMetric x, TimeMetric y)
  {
    return Equals(x.MetricText, y.MetricText);
  }

  public int GetHashCode(TimeMetric obj)
  {
    return obj.MetricText.GetHashCode();
  }
}

....

list.Distinct(new mtCompare());
14
Ritch Melton

個別のオーバーロードIEqualityComparer とともに使用できます。

IEqualityComparer実装のequalsメソッドは次のようになります。

bool Equals(TimeMetric x, TimeMetric y)
{
  return x.MetricText.Equals(y.MetricText);
}
3
David V