从具有最小值的KeyvaluePairs列表获取KeyValuePair

时间:2010-11-17 15:01:08

标签: c# .net

我需要从List<KeyValuePair<Int, Int>>列表中获取Kvp,具体取决于最小值。

我试过这个:

KeyValuePair<Int, Int> kvp= listOfKvps.Min(e=> e.Key);

但这只返回值,而不是我需要的整个KeyValuePair

3 个答案:

答案 0 :(得分:6)

var min = listOfKvps.OrderBy(kvp => kvp.Key).First();

如果你想通过一个 O(n)来完成序列,而不需要 O(n log n)排序,那么你可以这样做:

var min = listOfKvps.Aggregate((agg, kvp) => (kvp.Key < agg.Key) ? kvp : agg);

(当然,第二个版本的可读性/直觉性远远低于第一个版本,即使它确实具有更好的理论性能。使用某种MinBy方法会更有意义:要么自己编写,use the version from Marc's answeruse the version from MoreLINQ。)

答案 1 :(得分:4)

没有内置的MinBy方法,因此您可以 编写MinBy扩展方法,或仅.OrderBy(x => x.Key).First()MinBy将是O(n),因此效率更高 - 但需要编写更多代码; p

例如,您可以使用:

var kvp= listOfKvps.MinBy(e=> e.Key);

使用:

public static class SomeUtil {
    public static TSource MinBy<TSource, TValue>(
        this IEnumerable<TSource> source, Func<TSource, TValue> selector) {
        using (var iter = source.GetEnumerator())
        {
            if (!iter.MoveNext()) throw new InvalidOperationException("no data");
            var comparer = Comparer<TValue>.Default;
            var minItem = iter.Current;
            var minValue = selector(minItem);
            while (iter.MoveNext())
            {
                var item = iter.Current;
                var value = selector(item);
                if (comparer.Compare(minValue, value) > 0)
                {
                    minItem = item;
                    minValue = value;
                }
            }
            return minItem;
        }
    }   
}

答案 2 :(得分:2)

我建议您使用MoreLinq中的MinBy扩展名方法。

可替换地:

var minKey = listOfKvps.Min(kvp => kvp.Key);
var minKvp = listOfKvps.First(kvp => kvp.Key == minKey);

这仍然是O(n),虽然它需要2次通过列表。对列表进行排序然后选择第一个元素更简洁,但是O(n * logn),这可能与更大的列表相关。