2010-07-13 77 views
7

我有一个简单的类代表一个对象。它有5个属性(日期,2位小数,整数和字符串)。我有一个集合类,从CollectionBase派生,这是一个容器类,用于容纳来自我的第一个类的多个对象。如何使用LINQ查找并删除集合中的重复对象?

我的问题是,我想删除重复的对象(例如具有相同日期,相同小数,相同整数和相同字符串的对象)。是否有可以写入查找和删除重复项的LINQ查询?或者至少找到他们?

回答

10

您可以使用Distinct运算符删除重复项。

有两个重载 - 一个为你的类型使用默认的相等比较器(对于一个自定义类型将调用该类型的Equals()方法)。第二个允许你提供你自己的相等比较器。他们都返回新序列代表您的原始集没有重复。 重载实际上都不会修改您的初始集合 - 它们都返回排除重复的新序列。

如果你想只要找到重复的,你可以使用GroupBy这样做:

var groupsWithDups = list.GroupBy(x => new { A = x.A, B = x.B, ... }, x => x) 
         .Where(g => g.Count() > 1); 

要像一个IList<>删除重复,你可以这样做:

yourList.RemoveAll(yourList.Except(yourList.Distinct())); 
+0

这会将它们从我的集合中删除还是仅从LINQ查询中删除? – Icemanind 2010-07-13 17:05:17

+0

LINQ扩展方法创建新的项目集合,您的原始集合将保持不变。 – 2010-07-13 17:06:40

+0

感谢您的所有信息! – Icemanind 2010-07-13 17:21:36

4

如果简单班级使用Equals以满足您的要求的方式,然后您可以使用区别方法

var col = ...; 
var noDupes = col.Distinct(); 

如果没有,那么你将需要提供一个IEqualityComparer<T>的实例,它可以按照你所希望的方式比较值。例如(忽略简洁空问题)

public class MyTypeComparer : IEqualityComparer<MyType> { 
    public bool Equals(MyType left, MyType right) { 
    return left.Name == right.Name; 
    } 
    public int GetHashCode(MyType type) { 
    return 42; 
    } 
} 

var noDupes = col.Distinct(new MyTypeComparer()); 

注意事项GetHashCode使用常数是故意的。在不知道MyType的语义的详细细节的情况下,编写高效且正确的散列函数是不可能的。代替一个有效的哈希函数,我使用了一个常量,它与该类型的语义无关。

+0

这会从我的收藏中删除它们吗?或者只是LINQ查询? – Icemanind 2010-07-13 17:05:45

+0

@icemanind它将返回一个没有重复的新集合。它不会修改现有的集合。 – JaredPar 2010-07-13 17:07:06

+1

优秀的和最佳实践的答案 – danielea 2014-08-25 18:07:57