我有一个对象列表,类型可以是任何类型T
。
如何使用Linq选择仅在该列表中出现一次的对象列表?例如,如果我的列表是{2,3,4,5,8,2,3,5,4,2,3,4,6}
,则输出应为{6,8}
。
int[] arr = { 2, 3, 4, 5, 8, 2, 3, 5, 4, 2, 3, 4, 6 };
var q =
from g in arr.GroupBy(x => x)
where g.Count() == 1
select g.First();
int[] a = {2,3,4,5,8,2,3,5,4,2,3,4,6};
var selection = from i in a
where (a.Count(n => n == i) == 1)
select i;
方法 | 数组 | 平均时间(ns) | 相对值 | 误差 | 标准偏差 | Gen0 | Gen1 | 分配内存 | 相对值 |
---|---|---|---|---|---|---|---|---|---|
使用Linq获取唯一值 | Int32[10000] | 330,502.4ns | 100% | 3,771.44ns | 3,527.81ns | 62.5000 | 18.5547 | 294616 B | 100% |
使用Dictionary获取唯一值 | Int32[10000] | 161,602.2ns | 49% | 873.37ns | 774.22ns | 15.3809 | 2.4414 | 73336 B | 25% |
使用HashSet获取唯一值 | Int32[10000] | 120,871.6ns | 37% | 412.96ns | 366.07ns | 15.1367 | 2.0752 | 71616 B | 24% |
使用Linq获取唯一值 | Int32[1000] | 63,855.5ns | 100% | 813.66ns | 679.45ns | 18.6768 | 3.6621 | 88104 B | 100% |
使用Dictionary获取唯一值 | Int32[1000] | 27,243.4ns | 42% | 184.51ns | 172.59ns | 8.1787 | 0.0916 | 38600 B | 44% |
使用HashSet获取唯一值 | Int32[1000] | 22,269.1ns | 35% | 232.72ns | 217.68ns | 5.8289 | 0.2747 | 27440 B | [MemoryDiagnoser]
public class UniqueSelector
{
public IEnumerable<int[]> Data()
{
var rnd = new Random(1);
yield return new int[] { 2, 3, 4, 5, 8, 2, 3, 5, 4, 2, 3, 4, 6 };
yield return Enumerable.Range(0, 1000).Select(i => rnd.Next(1000)).ToArray();
yield return Enumerable.Range(0, 10000).Select(i => rnd.Next(1000)).ToArray();
}
[Benchmark]
[ArgumentsSource(nameof(Data))]
public int[] GetUniquesByLinq(int[] array)
{
var q =
from g in array.GroupBy(x => x)
where g.Count() == 1
select g.First();
return q.ToArray();
}
[Benchmark]
[ArgumentsSource(nameof(Data))]
public int[] GetUniquesByDictionary(int[] array)
{
var counts = new Dictionary<int, int>();
foreach (int item in array)
{
if (!counts.TryAdd(item, 1)) counts[item]++;
}
return counts.Where(kv => kv.Value == 1).Select(kv => kv.Key).ToArray();
}
[Benchmark]
[ArgumentsSource(nameof(Data))]
public int[] GetUniquesByHashSet(int[] array)
{
var uniques = new HashSet<int>();
var duplicates = new HashSet<int>();
foreach (int item in array)
{
if (duplicates.Contains(item)) continue;
if (uniques.Contains(item))
{
duplicates.Add(item);
uniques.Remove(item);
continue;
}
uniques.Add(item);
}
return uniques.ToArray();
}
}
|
T
编写一个测试相等性的方法。不过这是非常好的答案。 - Nick Larsen