找到具有最大值属性的元素的速度更快

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)

Dmi*_*nko 5

排序是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)


Ser*_*kiy 4

这两种解决方案都不是很有效。第一个解决方案涉及对整个集合进行排序。第二种解决方案需要遍历集合两次。但是您可以一次性找到具有最大属性值的项目,而无需对集合进行排序。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)