По умолчанию при использовании оператора Distinct linq используется метод Equals, но вы можете использовать свой собственный объект IEqualityComparer<T>
, чтобы указать, когда два объекта равны, с помощью пользовательской логики, реализующей метод GetHashCode
и Equals
.Помните, что:
GetHashCode
не следует использовать тяжелое сравнение с процессором (например, использовать только некоторые очевидные базовые проверки) и использовать его в качестве первого, чтобы указать, что два объекта наверняка различны (если возвращен другой хэш-код) илипотенциально то же самое (тот же хэш-код).В этом последнем случае, когда два объекта имеют одинаковый хэш-код, платформа будет проверять, используя метод Equals, как окончательное решение о равенстве заданных объектов.
После того, как у вас есть классы MyType
и MyTypeEqualityComparer
Код не гарантирует, что последовательность поддерживает свой порядок:
var cmp = new MyTypeEqualityComparer();
var lst = new List<MyType>();
// add some to lst
var q = lst.Distinct(cmp);
Далее sci library Я реализовал метод расширения, чтобы убедиться, что набор Vector3D поддерживает порядок при использовании определенного метода расширения DistinctKeepOrder
:
соответствующий код выглядит следующим образом:
/// <summary>
/// support class for DistinctKeepOrder extension
/// </summary>
public class Vector3DWithOrder
{
public int Order { get; private set; }
public Vector3D Vector { get; private set; }
public Vector3DWithOrder(Vector3D v, int order)
{
Vector = v;
Order = order;
}
}
public class Vector3DWithOrderEqualityComparer : IEqualityComparer<Vector3DWithOrder>
{
Vector3DEqualityComparer cmp;
public Vector3DWithOrderEqualityComparer(Vector3DEqualityComparer _cmp)
{
cmp = _cmp;
}
public bool Equals(Vector3DWithOrder x, Vector3DWithOrder y)
{
return cmp.Equals(x.Vector, y.Vector);
}
public int GetHashCode(Vector3DWithOrder obj)
{
return cmp.GetHashCode(obj.Vector);
}
}
Вкратце Vector3DWithOrder
инкапсулирует тип и целое число заказа, тогда как Vector3DWithOrderEqualityComparer
инкапсулирует оригинальный компаратор типа.
, и этовспомогательный метод для обеспечения порядка
/// <summary>
/// retrieve distinct of given vector set ensuring to maintain given order
/// </summary>
public static IEnumerable<Vector3D> DistinctKeepOrder(this IEnumerable<Vector3D> vectors, Vector3DEqualityComparer cmp)
{
var ocmp = new Vector3DWithOrderEqualityComparer(cmp);
return vectors
.Select((w, i) => new Vector3DWithOrder(w, i))
.Distinct(ocmp)
.OrderBy(w => w.Order)
.Select(w => w.Vector);
}
Примечание : дальнейшие исследования могут позволить найти более общий (использование интерфейсов) и оптимизированный способ (без инкапсуляции объекта).