C#

Sort Dictionary by Value in .NET

In this article, we are going to learn how to sort the values in the dictionary by their value.

To download the source code for this article, you can visit our GitHub repository.

Let’s begin.

Sorting by Value in Dictionary

In C#, the Dictionary type is used to hold a collection of key-value pairs. Since the dictionary uses a hash table internally, the key lookup is very fast. In certain scenarios, we might want to enumerate all the key-value pairs in the dictionary. But, ordered by their value.

In order to achieve this, let’s look at different ways, and then let’s do some benchmarks to know which is the most efficient way.

Before proceeding, we’ll create a simple dictionary of unordered values:

var dictionary = new Dictionary<string, string>
{
    { "1", "apple" },
    { "2", "orange" },
    { "3", "banana" },
    { "4", "grape" }
};

In this case, we are using the string type for both key and value in the dictionary. Henceforth, the dictionary’s type is Dictionary<string,string>.

Using the OrderBy() Method

The first way is to use the OrderBy() method available in LINQ. We can directly invoke this method on the dictionary:

var sortedKeyValuePairs = dictionary.OrderBy(x => x.Value).ToList();

Here, we are passing a lambda expression x => x.Value to the OrderBy() method. This will order the dictionary by its value. 

After ordering, we convert it to a list using the ToList() method. When we check the type of the list, it will be List<KeyValuePair<string,string>>. Here, each item in the list is represented as a KeyValuePair<TKey,TValue> type.

The reason we are not converting the ordered items back to the Dictionary<string,string> is that the dictionary cannot guarantee the same order upon enumeration. Hence, we need to preserve the ordered items in a list.

When we print the items in the list, we can see the ordered output:

1 apple
3 banana
4 grape
2 orange

If we want to sort the values in descending order, we can use the OrderByDescending() method.

Using LINQ Query Expression

An alternative way is to use the LINQ Query Expression syntax. Let’s quickly look at how to do it:

var sortedKeyValuePairs = (
    from keyValuePair in dictionary
    orderby keyValuePair.Value ascending
    select keyValuePair
).ToList();

Here, we are using the orderby clause on the keyValuePair.Value property. Additionally, we can use ascending or descending clause as per our needs.

Using the Sort() Method

The next way is to use the Sort() method. To use this method we need to first convert the dictionary to a list:

var sortedKeyValuePairs = dictionary.ToList();

And then, we can invoke the Sort() method on this list:

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

Please note that the Sort() method does not have a return value. It accepts a Comparision<T> delegate type where we can pass the lambda expression. The Sort() method uses this expression to sort the list.

Comparing Performance of Methods

So far so good. Now, let’s benchmark these three ways and find out the most performant way. We’ll use the BenchmarkDotNet library to do the benchmark for us.

We’ll use three different dictionary sizes (1000, 10,000, and 100,000) for the benchmark. Also, we populate the dictionary with 36 char GUID values:

public Dictionary<string, string> Generate(int count)
{
    var dictionary = new Dictionary<string, string>();
    for (var i = 0; i < count; i++)
    {
        dictionary.Add($"{i}", Guid.NewGuid().ToString());
    }

    return dictionary;
}

Let’s run the benchmark and wait for the result:

|                                      Method | dictionaryInput |         Mean |       Error |      StdDev |
|-------------------------------------------- |---------------- |-------------:|------------:|------------:|
|         SortDictionaryValueUsingLinqOrderBy |      1000 items |     514.5 us |     6.87 us |     6.42 us |
| SortDictionaryValueUsingLinqQueryExpression |      1000 items |     529.3 us |     7.73 us |     7.23 us |
|          SortDictionaryValueUsingSortMethod |      1000 items |     619.2 us |     2.82 us |     2.20 us |
|         SortDictionaryValueUsingLinqOrderBy |     10000 items |   7,580.4 us |    78.67 us |    73.59 us |
| SortDictionaryValueUsingLinqQueryExpression |     10000 items |   7,595.8 us |    32.51 us |    27.15 us |
|          SortDictionaryValueUsingSortMethod |     10000 items |   8,993.0 us |    31.95 us |    26.68 us |
|         SortDictionaryValueUsingLinqOrderBy |    100000 items | 117,477.4 us |   548.88 us |   486.57 us |
| SortDictionaryValueUsingLinqQueryExpression |    100000 items | 120,683.5 us |   881.49 us |   824.54 us |
|          SortDictionaryValueUsingSortMethod |    100000 items | 126,789.7 us | 1,181.45 us | 1,047.32 us |

From the result, we can see that the OrderBy() method is the fastest with a mean of 514.5 us, closely followed by the LINQ Query Expression with a mean of 529.3 us, and later followed by the Sort() method with a mean of 619.2 us for 1000 items in the dictionary. When the dictionary size increases, the time also increases proportionately. It is also important to note that there is no significant time difference between the three methods for smaller dictionaries.

Earlier we saw that the OrderBy() method is the simplest to implement and from the benchmark, we know that it is also the fastest. Therefore, it is a preferred option to sort the dictionary by value.

Conclusion

In this article, we’ve learned some of the different ways to sort a dictionary by value in C#. Later, from the benchmark, we found that the OrderBy() method is the fastest of all. However, we also found that there’s no significant difference between the three methods. If you’d like to learn more about sorting objects in lists, check out our article Sort List by Property in the Object in .NET.

Code Maze

View Comments

  • The SortDictionaryValueUsingLinqQueryExpression would literally be translated by the compiler into:

      var sortedKeyValuePairs = dictionary.OrderBy(x => x.Value).Select(x => x).ToList();
    
    

    That last Select() does nothing except add the little bit of overhead we see. I make a point of only using the query syntax when I'm using the select to project the data into a different object.

Share
Published by
Code Maze

Recent Posts

Code Maze Weekly #141

Issue #141 of the Code Maze weekly. Check out what's new this week and enjoy…

Updated Date Sep 30, 2022

How to Read AppSettings Values From a JSON File in .NET Core

In this post, we are going to learn how to read AppSettings values from a…

Sep 28, 2022

Counting Occurrences of a Char Within a String in C#

In this article, we are going to learn how to count occurrences of a char…

Updated Date Sep 29, 2022

How to Use Shouldly to Improve Unit Tests in .NET?

In this article, we are going to explore Shouldly. Shouldly is a library that improves…

Updated Date Sep 26, 2022

Code Maze Weekly #140

Issue #140 of the Code Maze weekly. Check out what's new this week and enjoy…

Updated Date Sep 23, 2022

Using Query String Parameters with Minimal APIs

In this article, we are going to explain how we can work with query string…

Updated Date Sep 22, 2022