测试列表中的所有值是否唯一

fre*_*hie 77 c#

我有一个小的字节列表,我想测试它们都是不同的值.例如,我有这个:

List<byte> theList = new List<byte> { 1,4,3,6,1 };
Run Code Online (Sandbox Code Playgroud)

检查所有值是否相同的最佳方法是什么?

jue*_*n d 139

bool isUnique = theList.Distinct().Count() == theList.Count();
Run Code Online (Sandbox Code Playgroud)

  • @dtb [应约为O(N)](http://stackoverflow.com/questions/2799427/what-guarantees-are-there-on-the-run-time-complexity-big-o-of-linq-方法).当然,考虑到这是一个"小清单",几乎任何算法都会闪电般快速.IMO在可读性和简洁性方面取得了成功,因为速度不是问题所在,这使得它变得完美. (9认同)
  • 这比可能的效率更高 (2认同)

Tim*_*ter 64

这是另一种比Enumerable.Distinct+ 更有效的方法Enumerable.Count(如果序列不是集合类型,则更多).它使用一个HashSet<T>消除重复,在查找中非常有效并具有count属性:

var distinctBytes = new HashSet<byte>(theList);
bool allDifferent = distinctBytes.Count == theList.Count;
Run Code Online (Sandbox Code Playgroud)

或另一种 - 更微妙和有效 - 的方法:

var diffChecker = new HashSet<byte>();
bool allDifferent = theList.All(diffChecker.Add);
Run Code Online (Sandbox Code Playgroud)

HashSet<T>.Addfalse如果元素无法添加,则返回,因为它已经在HashSet. Enumerable.All在第一个"假"停止.

  • 不,不需要。在这种情况下,您可以直接传递委托 (2认同)
  • @AndréReichelt - 我刚刚打开你的代码,第三种情况(`List.All(HashSet.Add)`)似乎在几乎所有情况下都比其他两种情况快得多 (2认同)

小智 10

Distinct与使用类似的逻辑GroupBy

var isUnique = theList.GroupBy(i => i).Count() == theList.Count;
Run Code Online (Sandbox Code Playgroud)

  • 如果您想检查属性 `theList.GroupBy(o =&gt; o.SomeProperty).Count() == theList.Count;` 的唯一性,而 Distinct() 不允许这样做,那么这非常有用。 (5认同)

Jod*_*ell 5

好的,这是我能想到的使用标准.Net的最有效方法

using System;
using System.Collections.Generic;

public static class Extension
{
    public static bool HasDuplicate<T>(
        this IEnumerable<T> source,
        out T firstDuplicate)
    {
        if (source == null)
        {
            throw new ArgumentNullException(nameof(source));
        }

        var checkBuffer = new HashSet<T>();
        foreach (var t in source)
        {
            if (checkBuffer.Add(t))
            {
                continue;
            }

            firstDuplicate = t;
            return true;
        }

        firstDuplicate = default(T);
        return false;
    }
}
Run Code Online (Sandbox Code Playgroud)

基本上,如果您想要做的就是找到第一个副本,那么两次枚举整个序列的重点是什么.

我可以通过特殊的套管对空元素和单个元素序列进行更多优化,但这会从可读性/可维护性中以最小的增益降低.

  • 为了可读性,我认为它应该是`if (!checkBuffer.Add(t)) { firstDuplicate = t; 在循环中返回 true }`。 (2认同)