Использование LINQ для поиска дубликатов по нескольким свойствам
Учитывая класс со следующим определением:
public class MyTestClass
{
public int ValueA { get; set; }
public int ValueB { get; set; }
}
Как можно дублировать значения в массиве MyTestClass []?
Например,
MyTestClass[] items = new MyTestClass[3];
items[0] = new MyTestClass { ValueA = 1, ValueB = 1 };
items[1] = new MyTestClass { ValueA = 0, ValueB = 1 };
items[2] = new MyTestClass { ValueA = 1, ValueB = 1 };
Содержит дубликат, поскольку есть два объекта MyTestClass, где ValueA и ValueB both = 1
Ответы
Ответ 1
Вы можете найти свои дубликаты, группируя свои элементы по ValueA и ValueB.
После этого подсчитайте их, и вы обнаружите, какие из них являются дубликатами.
Вот как вы изолировали бы обманы:
var duplicates = items.GroupBy(i => new {i.ValueA, i.ValueB})
.Where(g => g.Count() > 1)
.Select(g => g.Key);
Ответ 2
Вы можете просто использовать Jon Skeet DistinctBy
и Except
вместе, чтобы найти дубликаты. См. этот ответ для объяснения DistinctBy
.
MyTestClass[] items = new MyTestClass[3];
items[0] = new MyTestClass { ValueA = 1, ValueB = 1 };
items[1] = new MyTestClass { ValueA = 0, ValueB = 1 };
items[2] = new MyTestClass { ValueA = 1, ValueB = 1 };
MyTestClass [] distinctItems = items.DistinctBy(p => new {p.ValueA, p.ValueB}).ToArray();
MyTestClass [] duplicates = items.Except(distinctItems).ToArray();
Он возвращает только один элемент, а не оба дубликата.
Ответ 3
MyTestClass должен реализовать метод Equals.
public bool Equals(MyTestClass x, MyTestClass y)
{
if (Object.ReferenceEquals(x, y)) return true;
if (Object.ReferenceEquals(x, null) ||
Object.ReferenceEquals(y, null))
return false;
return x.ValueA == y.ValueA && y.ValueB == y.ValueB;
}
Здесь у вас есть хорошая статья об этом.
После этого вы можете получить "чистый" список MyTestClass с помощью метода "Distinct".