从列表中获取唯一项目[重复]

Posted

技术标签:

【中文标题】从列表中获取唯一项目[重复]【英文标题】:Getting unique items from a list [duplicate] 【发布时间】:2010-11-26 04:17:29 【问题描述】:

从列表中获取所有不同项目的最快/最有效的方法是什么?

我有一个List<string>,其中可能有多个重复项,并且只想要列表中的唯一值。

【问题讨论】:

这个问题的标题具有误导性。选择唯一项目是关于选择列表中仅出现一次的项目,而不是选择每个不同的元素一次。给定["A", "B", "C", "C", "D", "D"],唯一项将返回["A","B"],而不同项将返回["A", "B", "C", "D"] @EduardoPignatelli 相当挑剔,但这个问题可以毫不含糊地重新措辞。通常遇到的这个问题的意图是:“给定一个值列表,我如何在不重复任何值的情况下获得这些值的列表?” 【参考方案1】:

您可以使用Distinct 方法返回不同项目的IEnumerable<T>

var uniqueItems = yourList.Distinct();

如果您需要以List<T> 形式返回的唯一项目序列,您可以添加对ToList 的调用:

var uniqueItemsList = yourList.Distinct().ToList();

【讨论】:

OP 正在寻找一种快速/高效的方法。这不是它。调用yourList.Distinct().ToList() 需要对可枚举进行两次完整迭代,此外还基于IEqualityComparer,它比GetHashCode 慢。 这是否比 HashSet 更快/更高效?我不这么认为。不过,不必费心投反对票:-) @Noldorin, @Vinay: 如果 OP 需要以List 形式返回的不同项目,那么他们需要调用ToList,无论他们是否使用Distinct 或构造一个 HashSet。话虽如此,在大多数情况下,HashSet 的性能可能比Distinct 更好。 @Noldorin:我知道这很旧,但它很容易在 Google 上显示,你错了(至少,从 .NET 4 开始 - 我还没有检查旧版本)。 yourList.Distinct().ToList() 执行一次枚举, new HashSet(yourList).ToList() 执行两次。 HashSet 和 Distinct 的内部 Set 类的实现几乎完全相同。它们都使用 GetHashCode,并且都使用 IEqualityComparers(它们必须这样做,因为相等的哈希码(通常)不能保证相等的对象)。 @Noldorin:性能基准如何支持或反对我所说的?您可以通过在 Reflector(或其他 .NET 反编译器)中调出 System.Linq.Enumerable.DistinctIterator 和 System.Linq.Set 来验证我所说的,与相对性能无关。【参考方案2】:

使用HashSet<T>。例如:

var items = "A B A D A C".Split(' ');
var unique_items = new HashSet<string>(items);
foreach (string s in unique_items)
    Console.WriteLine(s);

打印

一种 乙 D C

【讨论】:

必须同意;别人解决问题,你解决原因:) A HashSet 不会维护任何排序,这可能是也可能不是 OP 的问题。 谢谢大家,我不需要订购这些物品。这很好用。【参考方案3】:

您可以使用 LINQ 中的Distinct 扩展方法

【讨论】:

【参考方案4】:

在 .Net 2.0 中,我很确定这个解决方案:

public IEnumerable<T> Distinct<T>(IEnumerable<T> source)

     List<T> uniques = new List<T>();
     foreach (T item in source)
     
         if (!uniques.Contains(item)) uniques.Add(item);
     
     return uniques;

【讨论】:

使用比 List 更快的随机访问集合,例如 Dictionary 或 HashSet。因为目前,如果source 包含 100,000 个具有许多重复项的项目,那么在 100,000 次迭代中的每一次迭代中,您将扫描大约 100,000 个项目的列表,这意味着您正在扫描 100,000 * 100,000 项目的顺序。二次时间复杂度会变得很慢。【参考方案5】:

除了 LINQ 的 Distinct 扩展方法之外,您还可以使用您的集合初始化的 HashSet&lt;T&gt; 对象。这很可能比 LINQ 方式更有效,因为它使用哈希码 (GetHashCode) 而不是 IEqualityComparer)。

事实上,如果它适合您的情况,我会首先使用HashSet 来存储项目。

【讨论】:

A HashSet 不会维护任何排序,这可能是也可能不是 OP 的问题。 @Luke: 即便如此,打电话给Distinct之后点餐就没有意义了... @Luke:这个问题询问最快/最有效,并且不需要维护订单。 @Noldorin:为什么不呢? Distinct 应该/确实按顺序迭代列表(尽管我不确定这是否真的在任何规范中得到保证)。 @Luke:哦,我真的在考虑索引。无论如何,OP 中提到了效率,而没有提到顺序(尽管这是一个悬而未决的问题)-HashSet 是您想要获得良好性能的方法。

以上是关于从列表中获取唯一项目[重复]的主要内容,如果未能解决你的问题,请参考以下文章

使用JS从列表中获取选定的项目[重复]

从python列表中获取元素的唯一组合[重复]

如何获取只有唯一数字的列表? (Python)

快速的独特组合(来自有重复的列表),无需查找

查找列表中不重复的项目数

从arraylist中获取不重复的项目[关闭]