За замовчуванням при використанні оператора Distinct linq використовується метод Equals, але ви можете використовувати власний IEqualityComparer<T>
об'єкт, щоб вказати, коли два об'єкти рівні, за допомогою реалізації користувацької логіки GetHashCode
таEquals
методу . Пам'ятайте, що:
GetHashCode
не слід використовувати важке порівняння процесорів (наприклад, використовувати лише деякі очевидні базові перевірки) і використовувати його як перший, щоб вказати, якщо два об'єкти, безумовно, відрізняються (якщо повертається різний хеш-код) або потенційно однакові (той самий хеш-код). У цьому останньому випадку, коли два об'єкти мають однаковий хеш-код, фреймворк буде перевіряти за допомогою методу Equals як остаточне рішення про рівність даних об'єктів.
Після того, як у вас є MyType
і MyTypeEqualityComparer
класи слідують коду, не переконайтеся, що послідовність підтримує свій порядок:
var cmp = new MyTypeEqualityComparer();
var lst = new List<MyType>();
var q = lst.Distinct(cmp);
У бібліотеці follow sci я реалізував метод розширення, щоб забезпечити підтримку набору Vector3D порядку, коли використовується певний метод розширенняDistinctKeepOrder
:
наступний код:
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
інкапсулюйте тип і ціле число порядку, whileVector3DWithOrderEqualityComparer
інкапсулює порівняльник оригінального типу.
і це помічник методу для забезпечення порядку
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);
}
Примітка : подальші дослідження можуть дозволити знайти більш загальний (використання інтерфейсів) та оптимізований спосіб (без інкапсуляції об’єкта).