【问题标题】:List<T> Where T is custom object. Remove duplicates by propertyList<T> 其中 T 是自定义对象。按属性删除重复项
【发布时间】:2012-08-20 18:01:30
【问题描述】:

我有一个List&lt;T&gt;,其中 T 是一个自定义对象。我的对象都不相等,但有些对象可能具有相等的属性。有什么快速的方法可以通过比较属性来删除重复项?哪些重复项留在列表中并不重要。

【问题讨论】:

  • 您是在尝试将属性与外部来源匹配,还是仅保留属性成员不同的项目?
  • @Pantelis 好的 - 我在答案中包含了这两个选项 - 以防万一;)但确实包含了一个选项。

标签: c# linq list generics


【解决方案1】:

您可以使用List&lt;T&gt;.RemoveAll 有效地执行此操作。

例如,如果您想删除所有 Foo 属性值为 42 的元素,您可以这样做:

theList.RemoveAll(i => i.Foo == 42);

如果您尝试按属性创建不同项目的列表,即:仅保留不同的 Foo 项目,我建议您执行以下操作:

HashSet<int> elements = new HashSet<int>(); // Type of property

theList.RemoveAll(i => !elements.Add(i.Foo));

这将跟踪哪些元素是“不同的”并删除所有其他元素。

【讨论】:

  • 本地HashSet&lt;T&gt;的精彩使用!
  • @JonSenchyna 这有点难看 IMO(因为谓词有副作用),但至少它是有效的。
  • 如果我错了,请纠正我,但这不会保留“不同”的属性,而是删除随后出现的重复属性。此调用的结果集将取决于元素的顺序,这与默认的Distinct 令人困惑。 (这可能是 OP 的意图,但需要注意的重要一点。)
  • @DanRasmussen Enumerable.Distinct 实际上就是这样工作的——它的实现与上面的非常相似——它使用一个 Set 来跟踪“找到”的项目,并且不包括后续找到的项目。
  • 在这种特殊情况下,提出问题的人明确表示保留哪些具有重复属性的对象并不重要,因此顺序依赖性也无关紧要。
【解决方案2】:

根据属性值对对象进行分组,然后选择每个组中的第一项。像这样:

var distinctObjects = objects
    .GroupBy(x => x.Property)
    .Select(g => g.First());

【讨论】:

  • 为什么不用键选择器Distinct
  • @Asti Enumerable.Distinct 上是否有过载?
  • @ChristofferLette:不,不是。它在morelinq 中以DistinctBy 的形式提供。
  • 我在想这样的超载会是模棱两可的。它会根据谓词(“where”-semantics)或不同的属性(“select”-semantics)返回不同的对象吗?
  • @ChristofferLette 我认为我一直在使用的那个必须属于System.Interactive 实验版本。
【解决方案3】:

您可以通过比较属性来创建一个实现IEqualityComparer&lt;T&gt; 的新类。然后,您可以使用 linq 的 Distinct 方法获取仅包含唯一元素的 IEnumerable。

【讨论】:

  • 这会很好用,但 Reed 的回答会表现得更好,并且不需要您为了单个方法调用而实现接口。
  • 谢谢,到目前为止我就是这样做的。抱歉忘了在我的问题中提及它。我正在寻找更简单的东西。
【解决方案4】:

你也可以从这里http://powercollections.codeplex.com/ 使用一个非常好的库并使用Algorithms.RemoveDuplicates 方法。那个图书馆有更多的收藏品。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-14
    • 1970-01-01
    • 1970-01-01
    • 2011-04-19
    • 2020-04-20
    • 1970-01-01
    相关资源
    最近更新 更多