2010-11-17 65 views
4

我需要根据最小值从List<KeyValuePair<Int, Int>>列表中获取Kvp。从KeyvaluePairs列表中获取一个KeyValuePair,其最小值为

我已经试过这样:

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

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

+1

该陈述似乎矛盾。如果你没有取回KeyValuePair,那么这个代码甚至不会编译。 – Dave 2010-11-17 15:04:54

+1

@Dave - 但它清楚地描述了OP想要做什么。我宁愿**有一个不编译但显示意图的例子,而不是编译的例子,但无法理解这个问题。 – 2010-11-17 15:11:50

回答

5

没有内置MinBy方法,所以你可以要么MinBy扩展方法,或者只是.OrderBy(x => x.Key).First()。一个MinByO(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

如果您使用MoreLINQ,则无需编写更多代码:morelinq.googlecode.com :) – 2010-11-17 15:08:14

+1

[Rx](http://thedailywtf.com/Articles/Extensible-XML.aspx)确实在“EnumerableEx”中添加了一个MinBy扩展方法类。所以人们可以期待该框架的未来版本。 – Richard 2010-11-17 15:11:25

5
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。)

+4

注意在时间上的排序是O(n lg n),在空间上是O(n);您可以在O(n)时间和O(1)空间中获取最小值。 – 2010-11-17 15:08:41

+0

@Eric:非常真实。我在发布原始答案后立即编辑它,但由于某种原因退出了SO,直到现在才回来! – LukeH 2010-11-17 15:23:57

+0

“Aggregate”版本为+1;我没有想到这一点。 – Ani 2010-11-17 15:32:36

1

我会建议你使用从MoreLinqMinBy扩展方法。

或者:

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

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

相关问题