I need to get a Kvp from a list of List<KeyValuePair<Int, Int>>
depending on the minimum value.
I have tried this:
KeyValuePair<Int, Int> kvp= listOfKvps.Min(e=> e.Key);
but this return only the value, not the whole KeyValuePair
which I need.
var min = listOfKvps.OrderBy(kvp => kvp.Key).First();
If you want to do it with a single O(n) pass through the sequence, rather than requiring an O(n log n) ordering, then you could do it like this:
var min = listOfKvps.Aggregate((agg, kvp) => (kvp.Key < agg.Key) ? kvp : agg);
(Of course, the second version is much less readable/intuitive than the first, even if it does have better theoretical performance. It would make more sense to use some sort of MinBy
method: either write your own, use the version from Marc's answer or use the version from MoreLINQ.)
There is no inbuilt MinBy
method, so you could either write a MinBy
extension method, or just .OrderBy(x => x.Key).First()
. A MinBy
would be O(n)
so would be more efficient - but more code to write ;p
For example, you could use:
var kvp= listOfKvps.MinBy(e=> e.Key);
with:
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;
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With