我有一个小字节列表,我想测试它们是否都是不同的值。例如,我有这个:
List<byte> theList = new List<byte> { 1,4,3,6,1 };
检查所有值是否不同的最佳方法是什么?
我有一个小字节列表,我想测试它们是否都是不同的值。例如,我有这个:
List<byte> theList = new List<byte> { 1,4,3,6,1 };
检查所有值是否不同的最佳方法是什么?
bool isUnique = theList.Distinct().Count() == theList.Count();
这是另一种比Enumerable.Distinct
+更有效的方法Enumerable.Count
(如果序列不是集合类型,则更有效)。它使用HashSet<T>
消除重复的 a ,在查找中非常有效并且具有计数属性:
var distinctBytes = new HashSet<byte>(theList);
bool allDifferent = distinctBytes.Count == theList.Count;
或另一种更微妙和更有效的方法:
var diffChecker = new HashSet<byte>();
bool allDifferent = theList.All(diffChecker.Add);
HashSet<T>.Add
如果false
元素已经在HashSet
. Enumerable.All
停在第一个“假”上。
好的,这是我能想到的使用标准 .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;
}
}
本质上,如果您只想找到第一个重复项,那么枚举整个序列两次的意义何在。
我可以通过特殊封装一个空的和单个元素的序列来优化它,但这会以最小的增益降低可读性/可维护性。
Distinct
与使用类似的逻辑GroupBy
:
var isUnique = theList.GroupBy(i => i).Count() == theList.Count;
也可以这样做:使用 Hashset
var uniqueIds = new HashSet<long>(originalList.Select(item => item.Id));
if (uniqueIds.Count != originalList.Count)
{
}
有很多解决方案。
毫无疑问,正如“juergen d”和“Tim Schmelter”提到的那样,使用 LINQ 会更漂亮。
但是,如果你裸露“复杂性”和速度,最好的解决方案就是自己实现它。解决方案之一是创建一个 N 大小的数组(字节为 256)。并循环数组,并且在每次迭代中,如果值为 1,则测试匹配的数字索引,这意味着我已经增加了数组索引,因此数组不是不同的,否则我将增加数组单元格并继续检查.
还有另一个解决方案,如果你想找到重复的值。
var values = new [] { 9, 7, 2, 6, 7, 3, 8, 2 };
var sorted = values.ToList();
sorted.Sort();
for (var index = 1; index < sorted.Count; index++)
{
var previous = sorted[index - 1];
var current = sorted[index];
if (current == previous)
Console.WriteLine(string.Format("duplicated value: {0}", current));
}
输出:
duplicated value: 2
duplicated value: 7
我检查一个 IEnumerable (aray, list, etc) 是否像这样是唯一的:
var isUnique = someObjectsEnum.GroupBy(o => o.SomeProperty).Max(g => g.Count()) == 1;