2011-11-29 49 views
18

所以我知道如何通过使用Linq中的Distinct()来删除列表中的重复项,以及字符串和整型等。但是,如何根据对象的特定属性删除重复项?删除列表中的重复对象(C#)

例如,我有一个TimeMetric类。这个TimeMetric类有两个属性:MetricTextMetricTime。我有一个TimeMetrics名为MetricList的清单。我想删除具有相同MetricText属性的任何重复项TimeMetricTimeMetric的值可以相同,但如果有任何TimeMetric具有相同的MetricText,它必须是不重复的。

回答

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()); 
3

可以使用Distinct overloadIEqualityComparer

你对于自己的IEqualityComparer实现equals方法是这样的:

bool Equals(TimeMetric x, TimeMetric y) 
{ 
    return x.MetricText.Equals(y.MetricText); 
} 
+1

这是不正确的,并且只会在MetricText的类型为'string'(或者覆盖'operator ==' )。应该使用“Equals”。 – Jon

+0

我认为这是一个字符串,这不是一个好的假设,并更新了回应。 –

14

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