2010-11-17 116 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),這可能與較大的列表有關。

相關問題