Как найти и удалить дубликаты объектов в коллекции с помощью LINQ? - PullRequest
7 голосов
/ 13 июля 2010

У меня есть простой класс, представляющий объект. У него 5 свойств (дата, 2 десятичных знака, целое число и строка). У меня есть класс коллекции, производный от CollectionBase, который является контейнерным классом для хранения нескольких объектов из моего первого класса.

У меня вопрос: я хочу удалить дубликаты объектов (например, объекты с одинаковой датой, одинаковыми десятичными числами, одинаковыми целыми числами и одинаковой строкой) Можно ли написать запрос LINQ для поиска и удаления дубликатов? Или найти их как минимум?

Ответы [ 2 ]

11 голосов
/ 13 июля 2010

Вы можете удалить дубликаты, используя оператор 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() ) );
4 голосов
/ 13 июля 2010

Если ваш простой класс использует Equals таким образом, который удовлетворяет вашим требованиям, тогда вы можете использовать метод Distinct

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, невозможно написать эффективную и правильную функцию хеширования.Вместо эффективной функции хеширования я использовал константу, которая является правильной независимо от семантики типа.

...