How do you sort a dictionary by value?

Viewed 745335

I often have to sort a dictionary (consisting of keys & values) by value. For example, I have a hash of words and respective frequencies that I want to order by frequency.

There is a SortedList which is good for a single value (say frequency), that I want to map back to the word.

SortedDictionary orders by key, not value. Some resort to a custom class, but is there a cleaner way?

21 Answers

Use LINQ:

Dictionary<string, int> myDict = new Dictionary<string, int>();
myDict.Add("one", 1);
myDict.Add("four", 4);
myDict.Add("two", 2);
myDict.Add("three", 3);

var sortedDict = from entry in myDict orderby entry.Value ascending select entry;

This would also allow for great flexibility in that you can select the top 10, 20 10%, etc. Or if you are using your word frequency index for type-ahead, you could also include StartsWith clause as well.

Use:

using System.Linq.Enumerable;
...
List<KeyValuePair<string, string>> myList = aDictionary.ToList();

myList.Sort(
    delegate(KeyValuePair<string, string> pair1,
    KeyValuePair<string, string> pair2)
    {
        return pair1.Value.CompareTo(pair2.Value);
    }
);

Since you're targeting .NET 2.0 or above, you can simplify this into lambda syntax -- it's equivalent, but shorter. If you're targeting .NET 2.0 you can only use this syntax if you're using the compiler from Visual Studio 2008 (or above).

var myList = aDictionary.ToList();

myList.Sort((pair1,pair2) => pair1.Value.CompareTo(pair2.Value));

Looking around, and using some C# 3.0 features we can do this:

foreach (KeyValuePair<string,int> item in keywordCounts.OrderBy(key=> key.Value))
{ 
    // do something with item.Key and item.Value
}

This is the cleanest way I've seen and is similar to the Ruby way of handling hashes.

On a high level, you have no other choice than to walk through the whole Dictionary and look at each value.

Maybe this helps: http://bytes.com/forum/thread563638.html Copy/Pasting from John Timney:

Dictionary<string, string> s = new Dictionary<string, string>();
s.Add("1", "a Item");
s.Add("2", "c Item");
s.Add("3", "b Item");

List<KeyValuePair<string, string>> myList = new List<KeyValuePair<string, string>>(s);
myList.Sort(
    delegate(KeyValuePair<string, string> firstPair,
    KeyValuePair<string, string> nextPair)
    {
        return firstPair.Value.CompareTo(nextPair.Value);
    }
);

You'd never be able to sort a dictionary anyway. They are not actually ordered. The guarantees for a dictionary are that the key and value collections are iterable, and values can be retrieved by index or key, but there is no guarantee of any particular order. Hence you would need to get the name value pair into a list.

Actually in C#, dictionaries don't have sort() methods. As you are more interested in sort by values, you can't get values until you provide them key. In short, you need to iterate through them using LINQ's OrderBy(),

var items = new Dictionary<string, int>();
items.Add("cat", 0);
items.Add("dog", 20);
items.Add("bear", 100);
items.Add("lion", 50);

// Call OrderBy() method here on each item and provide them the IDs.
foreach (var item in items.OrderBy(k => k.Key))
{
    Console.WriteLine(item);// items are in sorted order
}

You can do one trick:

var sortedDictByOrder = items.OrderBy(v => v.Value);

or:

var sortedKeys = from pair in dictName
            orderby pair.Value ascending
            select pair;

It also depends on what kind of values you are storing: single (like string, int) or multiple (like List, Array, user defined class). If it's single you can make list of it and then apply sort.
If it's user defined class, then that class must implement IComparable, ClassName: IComparable<ClassName> and override compareTo(ClassName c) as they are more faster and more object oriented than LINQ.

Required namespace : using System.Linq;

Dictionary<string, int> counts = new Dictionary<string, int>();
counts.Add("one", 1);
counts.Add("four", 4);
counts.Add("two", 2);
counts.Add("three", 3);

Order by desc :

foreach (KeyValuePair<string, int> kvp in counts.OrderByDescending(key => key.Value))
{
// some processing logic for each item if you want.
}

Order by Asc :

foreach (KeyValuePair<string, int> kvp in counts.OrderBy(key => key.Value))
{
// some processing logic for each item if you want.
}

Sort and print:

var items = from pair in players_Dic
                orderby pair.Value descending
                select pair;

// Display results.
foreach (KeyValuePair<string, int> pair in items)
{
    Debug.Log(pair.Key + " - " + pair.Value);
}

Change descending to acending to change sort order

A dictionary by definition is an unordered associative structure that contains only values and keys in a hashable way. In other words has not a previsible way to orderer a dictionary.

For reference read this article from python language.

Link python data structures

Best way:

var list = dict.Values.OrderByDescending(x => x).ToList();
var sortedData = dict.OrderBy(x => list.IndexOf(x.Value));
Related