获取KeyValuePair,其中Key为最小值(来自IEnumerable)

时间:2019-05-05 18:16:06

标签: c# .net linq

所以...我问过去9年是否发生了变化,现在该问题已经作为10年前的问题和答案的重复项被关闭。

我知道我可以得到最小的Key,然后使用它。像这样:

theEnumerable[theEnumerable.Min(a => a.Key)];

但是有直接方法吗?据我所知,还没有9年前。但这是很长一段时间。 (然后刚刚发布了Windows Phone(不是“ Mobile”!)。)

(我也可以OrderBy然后拿走First(),但这非常很浪费。)

1 个答案:

答案 0 :(得分:0)

因此,您有一系列相似的项目,其中每个项目至少具有一个属性Key,该属性的类型可以实现IComparable。

您需要从序列中的所有项目中选择属性Key的值最低的项目。如果有几个具有相同的最低价值,那么您就不在乎得到哪个。

如果这样写,解决方案很简单:

var result = myKeyValuePairs.OrderBy(keyValuePair => keyValuePair.Key).FirstOrDefault();

换句话说:采用原始的keyValuePairs序列。按keyValuePair.Key的值升序排列此序列,从所得序列中取第一个,如果序列为空,则返回null。

尽管这很有效,尽管看起来很容易理解,但是如果只需要最小的第二个,第三个最小的等等,订购第二个最小,第三个最小的不是很有效。

一种更有效的方法是使用Enumerable.Aggregate。不过请小心,此功能仅在确定序列中至少有一个元素时才有效。如果不是,则应首先断言该序列不为空。

if (myKeyValuePairs.Any())
    return myKeyValuePairs.Aggregate( (lowestPair, currentPair) =>
           (lowestPair.Key <= currentPair.Key) ? lowestPair : currentPair);
else
    return null;

但是,由于Any(),您将枚举第一个元素两次。除了每个循环之外,您还要进行分配。

一个甚至更优化的代码(只需精确枚举一次序列)将是扩展功能,例如:

TSource SmallestOrDefault<TSource, TResult>(this IEnumerable<TSource> source,
    Func<TSource, Tkey> keySelector)
    {
        // TODO: check null source or keySelector
        IEnumerator<TSource> enumerator = source.GetEnumerator();

        if (enumerator.MoveNext())
        {
             // sequence not empty. The first element is smallest until now
             TSource smallestElement = enumerator.Current;

             // check the rest of the sequence to see if there are smaller elements
             while (enumerator.MoveNext)
             {
                 // there is a next element. Is it smaller?
                 if (enumerator.Current < smallestElement)
                 {
                      // found a new smallest element
                      smallestElement = enumerator.Current;
                 }
             } 
             return smallestElement;
       }
       else
           // empty sequence
           return null;
    }

用法:

var smallestElement = myKeyValuePairs.SmallestOrDefault(
      keyValuePair => keyValuePair.Key);