Kon*_*ran 7 c# linq collections performance
通常,要找到具有最大值属性的元素,我喜欢这样
var itemWithMaxPropValue = collection.OrderByDescending(x => x.Property).First();
Run Code Online (Sandbox Code Playgroud)
但从性能的角度来看,这是好方法吗?也许我应该做这样的事情?
var maxValOfProperty = collection.Max(x => x.Property);
var itemWithMaxPropValue = collection
.Where(x => x.Property == maxValueOfProperty).First();
Run Code Online (Sandbox Code Playgroud)
排序是N * log (N)同时具有最大N只有时间复杂度,因此Max是更快的.您要查找的是ArgMax其功能的LINQ不提供,所以我建议实施它,比如:
public static class EnumerableExtensions {
public static T ArgMax<T, K>(this IEnumerable<T> source,
Func<T, K> map,
IComparer<K> comparer = null) {
if (Object.ReferenceEquals(null, source))
throw new ArgumentNullException("source");
else if (Object.ReferenceEquals(null, map))
throw new ArgumentNullException("map");
T result = default(T);
K maxKey = default(K);
Boolean first = true;
if (null == comparer)
comparer = Comparer<K>.Default;
foreach (var item in source) {
K key = map(item);
if (first || comparer.Compare(key, maxKey) > 0) {
first = false;
maxKey = key;
result = item;
}
}
if (!first)
return result;
else
throw new ArgumentException("Can't compute ArgMax on empty sequence.", "source");
}
}
Run Code Online (Sandbox Code Playgroud)
所以你可以简单地说
var itemWithMaxPropValue = collection
.ArgMax(x => x.Property);
Run Code Online (Sandbox Code Playgroud)
这两种解决方案都不是很有效。第一个解决方案涉及对整个集合进行排序。第二种解决方案需要遍历集合两次。但是您可以一次性找到具有最大属性值的项目,而无需对集合进行排序。MoreLINQ库中有 MaxBy 扩展。或者您可以实现相同的功能:
public static TSource MaxBy<TSource, TProperty>(this IEnumerable<TSource> source,
Func<TSource, TProperty> selector)
{
// check args
using (var iterator = source.GetEnumerator())
{
if (!iterator.MoveNext())
throw new InvalidOperationException();
var max = iterator.Current;
var maxValue = selector(max);
var comparer = Comparer<TProperty>.Default;
while (iterator.MoveNext())
{
var current = iterator.Current;
var currentValue = selector(current);
if (comparer.Compare(currentValue, maxValue) > 0)
{
max = current;
maxValue = currentValue;
}
}
return max;
}
}
Run Code Online (Sandbox Code Playgroud)
用法很简单:
var itemWithMaxPropValue = collection.MaxBy(x => x.Property);
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1477 次 |
| 最近记录: |