如何使用LINQ查找和删除集合中的重复对象?

时间:2010-07-13 17:02:19

标签: c# .net linq collections duplicates

我有一个表示对象的简单类。它有5个属性(日期,2位小数,一个整数和一个字符串)。我有一个派生类,派生自CollectionBase,它是一个容器类,用于从我的第一个类中保存多个对象。

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

2 个答案:

答案 0 :(得分:11)

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

答案 1 :(得分:4)

如果您的简单课程以满足您要求的方式使用Equals,那么您可以使用Distinct方法

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

如果没有,则需要提供IEqualityComparer<T>的实例,以您希望的方式比较值。例如(为简洁起见忽略了null问题)

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语义的私密细节,就不可能编写有效且正确的散列函数。代替有效的散列函数,我使用了一个正确的常量,而不管该类型的语义如何。