如何快速在List<T>中查找重复项,并更新原始集合

5
让我先说一下,我已经阅读了以下这些问题:12,我知道我可以编写代码来查找列表中的重复项,但我的问题是,我想要更新原始列表,而不仅仅是查询并打印重复项。
我知道我无法更新查询返回的集合,因为它不是视图,而是一个匿名类型的IEnumerable。
我想能够在我的列表中查找重复项,并标记一个我创建的属性State,在应用程序的后续使用中会用到此属性。
有人遇到过这个问题吗?你能指点我方向吗?
P.S. 我目前使用的方法是类似冒泡排序的循环,逐个遍历列表项并比较关键字段。显然,这不是最快的方法。
编辑:
为了认为列表中的条目是“重复项”,必须匹配三个字段。我们称它们为Field1、Field2和Field3。
我在基类上有一个重载的Equals()方法,用于比较这些字段。
我在我的MarkDuplicates()方法中跳过对象的唯一一次,是如果对象的状态为未知或错误,否则我就进行测试。
如果您需要更多细节,请告诉我。
再次感谢!

1
请不要使用冒泡排序……永远不要! - Mitch Wheat
3个回答

8

我认为最简单的方法是编写一个扩展方法,用于在对象列表中查找重复项。由于您的对象使用.Equals()进行比较,它们可以在大多数常见集合中进行比较。

public static IEnumerable<T> FindDuplicates<T>(this IEnumerable<T> enumerable) {
  var hashset = new HashSet<T>();
  foreach ( var cur in enumerable ) { 
    if ( !hashset.Add(cur) ) {
      yield return cur;
    }
  }
}

现在更新集合中的重复项应该很容易。例如:
List<SomeType> list = GetTheList();
list
  .FindDuplicates()
  .ToList()
  .ForEach(x => x.State = "DUPLICATE");

如果您的代码中已经定义了一个 ForEach 扩展方法,您可以避免使用 .ToList。

1

你的对象具有某种状态属性。你可能是基于另一个属性或一组属性来查找重复项。为什么不这样做:

List<obj> keys = new List<object>();

foreach (MyObject obj in myList)
{
    if (keys.Contains(obj.keyProperty))
        obj.state = "something indicating a duplicate here";
    else
        keys.add(obj.keyProperty)
}

这个问题的解决方法是使用一个列表来存储“键”,但如果你有很多对象,最好使用 HashSet 来代替列表。 - mqp

1
IEnumerable<T> oldList;
IEnumerable<T> list;

foreach (var n in oldList.Intersect(list))
   n.State = "Duplicate";

编辑:我需要学会认真阅读。这段代码是针对2个列表的。我的错。


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