使用LINQ查找跨多个属性的重复项

30

给定以下定义的类:

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对象,其中ValueAValueB都等于1,因此包含重复项。

3个回答

60
你可以根据ValueA和ValueB将元素分组,以此找到重复项。 之后进行计数,即可找出哪些是重复项。
以下为如何隔离重复项的方法:
var duplicates = items.GroupBy(i => new {i.ValueA, i.ValueB})
  .Where(g => g.Count() > 1)
  .Select(g => g.Key);

2
正是我所需要的!你赢得了互联网。非常感谢。 - CatBusStop

5
您可以结合使用Jon Skeet的DistinctByExcept来查找重复项。请参见此响应,了解他对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();

它只会返回一个项目,而不是两个重复的项目。

1

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;
}

这里有一篇好文章与此相关。

之后,您可以使用“Distinct”方法获得“干净”的MyTestClass列表。


2
如果要让Distinct方法正常工作,你需要做的不仅仅是实现Equals方法。你还应该实现IEquatable<MyTestClass>接口,并确保正确实现GetHashCode和对象相等性。 - Hugo Migneron
没错,是我的错;-)不管怎样,这并不需要太多的工作...在许多场景下都可能很有趣;-) - zapico

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接