我一直在尝试让 Linq 查询从集合中返回不同的值。我找到了两种方法来解决这个问题;使用 GroupBy 或 Distinct。 我知道 Distinct 是为了这项工作而设计的,但我必须在对象上实现 IEquatable。
我尝试了 GroupBy,效果很好。我想知道使用 Distinct 与 GroupBy 是否具有明显的性能优势。
Distinct()
将比较集合中的整个对象(对于引用类型,您需要覆盖 GetHashCode 和 Equals)。它将枚举项目并将它们添加到集合中。简单又快速。比如:
Set<TSource> set = new Set<TSource>(comparer);
foreach (TSource tSource in source)
{
if (!set.Add(tSource))
continue;
yield return tSource;
}
GroupBy()
允许您通过某个键对对象进行分组。在这种情况下,将比较键。它将需要为集合中的每个项目执行键选择器 lambda。此外,它还需要为每个不同的键创建分组,并将集合中的每个项目添加到其组中:
Func<TSource, TElement> elementSelector = x => x;
<TKey, TElement> lookup = new Lookup<TKey, TElement>(comparer);
foreach (TSource tSource in source)
{
TKey key = keySelector(tSource);
// simplified pseudo-code
if (!lookup.Contains(key))
lookup.Add(new Grouping(key));
lookup[key].Add(elementSelector(tSource));
}
foreach(IGrouping<TKey, TElement> grouping in lookup)
yield return grouping;
所以,我认为
GroupBy()
并没有那么简单Distict()
那么快。
老问题,但我刚才偶然发现了这个问题,并决定使用 BenchmarkDotNet 运行基准测试。 注意:问题中没有具体说明,我认为它要求的是内存中的性能。
[Benchmark]
public bool GroupBy_Count_IEnumerable()
{
return list.GroupBy(x => x.Property).Count() > 1;
}
[Benchmark]
public bool SelectDistinct_Count_IEnumerable()
{
return list.Select(x => x.Property).Distinct().Count() > 1;
}
结果是:
Select(x => x.Property).Distinct()
比 GroupBy(x => x.Property)
快。
200 件:
方法 | 意思是 | 错误 | 标准偏差 |
---|---|---|---|
GroupBy_Count_IEnumerable | 11.537 我们 | 0.4056 我们 | 1.1703 我们 |
选择Distinct_Count_IEnumerable | 5.660 我们 | 0.0894 我们 | 0.0792 我们 |
50_000 件商品:
方法 | 意思是 | 错误 | 标准偏差 | 中位数 |
---|---|---|---|---|
GroupBy_Count_IEnumerable | 7.750 毫秒 | 0.1527 毫秒 | 0.2978 毫秒 | 7.631 毫秒 |
选择Distinct_Count_IEnumerable | 5.352 毫秒 | 0.1064 毫秒 | 0.2747 毫秒 | 5.280 毫秒 |