在列表中移除重复对象(C#)

18

我知道如何在处理字符串和整数等时使用Linq中的Distinct()来删除列表中的重复项。但是,如何基于对象的特定属性删除重复项呢?

例如,我有一个TimeMetric类,这个类有两个属性:MetricTextMetricTime。我有一个名为MetricListTimeMetrics列表。我想删除任何具有相同MetricText属性的重复TimeMetricTimeMetric的值可以相同,但如果任何TimeMetric具有相同的MetricText,则必须将其去重。

3个回答

21

你需要使用Distinct的第二个重载,该重载需要一个IEqualityComparer<TimeMetric>实例作为第二个参数。定义一个类似这样的比较器:

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)。如果MetricTextnull,应该进行检查,并从GetHashCode返回0。另一方面,如果MetricText的类型是值类型,则不需要执行任何修改。

然后:

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

15

使用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());

3
你可以使用Distinct overloadIEqualityComparer一起使用。
你的IEqualityComparer实现中的equals方法应该像这样:
bool Equals(TimeMetric x, TimeMetric y)
{
  return x.MetricText.Equals(y.MetricText);
}

1
这是不正确的,只有当MetricTextstring类型(或另一种重写了operator ==的类型)时才能正常工作。应该使用Equals - Jon
我假设它是一个字符串,这不是一个好的假设,并更新了响应。 - David V

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接