Hristo Hristov
Hristo Hristov

Reputation: 31

How to sort a Dictionary<string, List<int>> by a certain element in values list?

I have a dictionary which holds strings as keys and Lists as values. Imagine you have Olympic Games where the keys are different countries and the values in each list are for example number of participants, number of sports, gold medals, silver medals, etc. So if I want to sort the countries by gold medals and say gold medals is the second entry in each list I would want something like this:

var countryRankings = new Dictionary<string, List<int>>();
countryRankings.Add(country, new List<int>() {numberOfParticipants, numberOfWins });
//some more country data follows
countryRankings.OrderByDescending(pairs => pairs.Value[1]);

The last bit is not rejected by VisualStudio but is not working as expected. The dictionary is not sorted.When I think about it it's better to create class country with different properties and then sort with Lambda in the way OrderBy(c => c.goldMedals) but is there a way to do this with nested inside a dictionary List ?

Upvotes: 3

Views: 1875

Answers (2)

Guffa
Guffa

Reputation: 700850

The OrderByDescending method doesn't sort the dictionary, it returns a new collection that is sorted.

Assign the result to a variable. It can't be a dictionary though, as the items in a dictionary can't be reordered. You can use the ToList method to realise the result as an actual collection:

List<KeyValuePair<string, List<int>>> result =
  countryRankings.OrderByDescending(pairs => pairs.Value[1]).ToList();

Using a class instead of a list of integers would be better, but it doesn't change what you need to do to get the sorted result, only what the expression to sort it looks like.

Upvotes: 1

Mike Dinescu
Mike Dinescu

Reputation: 55760

That's because the OrderByDescending extension method does not mutate (modify) the original object (countryRankings) but instead returns another object that, when enumerated, produces ordered references to elements in the original dictionary.

So, this should work:

var orderedRankings = countryRankings.OrderByDescending(pairs => pairs.Value[1]); 
// now you can iterate over orderedRankings
foreach(var rankingPair in orderedRankings)
{
    // do something with it..
}

And, yes it would be better to create a class as you suggested in the last part of the question but that doesn't change the answer.

Upvotes: 4

Related Questions