views:

259

answers:

4

I'm trying to get the key of the maximum value in the Dictionary<string, double> results.

This is what I have so far:

double max = results.Max(kvp => kvp.Value);
return results.Where(kvp => kvp.Value == max).Select(kvp => kvp.Key).First();

However, since this seems a little inefficient, I was wondering whether there was a better way to do this.

+2  A: 

This is a fast method. It is O(n), which is optimal. The only problem I see is that it iterates over the dictionary twice instead of just once.

You can do it iterating over the dictionary once by using MaxBy from morelinq.

results.MaxBy(kvp => kvp.Value).Key;
Mark Byers
@Mark `Aggregate` can also be used for the same effect.
dss539
A: 

I think using the standard LINQ Libraries this is as fast as you can go.

PSU_Kardi
@PSU_Kardi Not quite. ;)
dss539
+5  A: 

Maybe this isn't a good use for LINQ. I see 2 full scans of the dictionary using the LINQ solution (1 to get the max, then another to find the kvp to return the string.

You could do it in 1 pass with an "old fashioned" foreach:


KeyValuePair<string, double> max = new KeyValuePair<string, double>(); 
foreach (var kvp in results)
{
  if (kvp.Value > max.Value)
    max = kvp;
}
return max.Key;

JMarsch
I know it leads to the same result but I have found this to be more readable: `var max = default(KeyValuePair<string, double>);`
ChaosPandion
@JMarsch You are right; the OP had an O(2n) algorithm using see. See my answer for a O(n) using LINQ.
dss539
+1 for reducing the iterations. You should probably initialize max.Value with double.MinValue to ensure you find a max even if it is a negative.
Chris Taylor
+9  A: 

I think this is the most readable O(n) answer using standard LINQ.

var max = results.Aggregate((l, r) => l.Value > r.Value ? l : r).Key;
dss539
+1 dss539: I had an itch in my brain, like there should have been some way to do it with LINQ. Nice!
JMarsch