Что такое «многосортная алгебра» и как я могу использовать ее для решения «реальных проблем»?

Если вы не хотите добавлять библиотеку MoreLinq в свой проект, чтобы получить функциональность DistinctBy, вы можете получить тот же конечный результат, используя перегрузку метода Linq Distinct, который принимает аргумент IEqualityComparer .

Вы начинаете с создания общего пользовательского класса сравнения сравнений, который использует синтаксис лямбда для выполнения пользовательского сравнения двух экземпляров родового класса:

public class CustomEqualityComparer<T> : IEqualityComparer<T>
{
    Func<T, T, bool> _comparison;
    Func<T, int> _hashCodeFactory;

    public CustomEqualityComparer(Func<T, T, bool> comparison, Func<T, int> hashCodeFactory)
    {
        _comparison = comparison;
        _hashCodeFactory = hashCodeFactory;
    }

    public bool Equals(T x, T y)
    {
        return _comparison(x, y);
    }

    public int GetHashCode(T obj)
    {
        return _hashCodeFactory(obj);
    }
}

Затем в вашем основном коде вы используйте его так:

Func<Person, Person, bool> areEqual = (p1, p2) => int.Equals(p1.Id, p2.Id);

Func<Person, int> getHashCode = (p) => p.Id.GetHashCode();

var query = people.Distinct(new CustomEqualityComparer<Person>(areEqual, getHashCode));

Voila! :)

Вышеприведенное предполагает следующее:

  • Свойство Person.Id имеет тип int
  • Коллекция people не содержит любые нулевые элементы

Если коллекция может содержать нули, то просто перепишите lambdas для проверки нулевого значения, например:

Func<Person, Person, bool> areEqual = (p1, p2) => 
{
    return (p1 != null && p2 != null) ? int.Equals(p1.Id, p2.Id) : false;
};

EDIT

Такой подход аналогичен такому в ответе Владимира Нестеровского, но проще.

Он также похож на ответ Джоэла, но допускает сложную логику сравнения, включающую несколько свойств.

Однако, если ваши объекты могут отличаться только на Id, другой пользователь дал правильный ответ, что все, что вам нужно сделать, это переопределить реализации по умолчанию GetHashCode() и Equals() в вашем Person, а затем просто используйте готовый метод Distinct() Linq для фильтрации любых дубликатов.

30
задан Peter O. 23 October 2013 в 06:28
поделиться