Good way to get the key of the highest value of a Dictionary in C#

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.


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;

edit: explanation for CoffeeAddict

Aggregate is the LINQ name for the commonly known functional concept Fold

It loops over each element of the set and applies whatever function you provide. Here, the function I provide is a comparison function that returns the bigger value. While looping, Aggregate remembers the return result from the last time it called my function. It feeds this into my comparison function as variable l. The variable r is the currently selected element.

So after aggregate has looped over the entire set, it returns the result from the very last time it called my comparison function. Then I read the .Key member from it because I know it's a dictionary entry

Here is a different way to look at it [I don't guarantee that this compiles ;) ]

var l = results[0];
for(int i=1; i<results.Count(); ++i)
{
    var r = results[i];
    if(r.Value > l.Value)
        l = r;        
}
var max = l.Key;

After reading various suggestions, I decided to benchmark them and share the results.

The code tested:

// TEST 1

for (int i = 0; i < 999999; i++)
{
  KeyValuePair<GameMove, int> bestMove1 = possibleMoves.First();
  foreach (KeyValuePair<GameMove, int> move in possibleMoves)
  {
    if (move.Value > bestMove1.Value) bestMove1 = move;
  }
}

// TEST 2

for (int i = 0; i < 999999; i++)
{
  KeyValuePair<GameMove, int> bestMove2 = possibleMoves.Aggregate((a, b) => a.Value > b.Value ? a : b);
}

// TEST 3

for (int i = 0; i < 999999; i++)
{
  KeyValuePair<GameMove, int> bestMove3 = (from move in possibleMoves orderby move.Value descending select move).First();
}

// TEST 4

for (int i = 0; i < 999999; i++)
{
  KeyValuePair<GameMove, int> bestMove4 = possibleMoves.OrderByDescending(entry => entry.Value).First();
}

The results:

Average Seconds Test 1 = 2.6
Average Seconds Test 2 = 4.4
Average Seconds Test 3 = 11.2
Average Seconds Test 4 = 11.2

This is just to give an idea of their relative performance.

If your optimizing 'foreach' is fastest, but LINQ is compact and flexible.