The C# language does not provide a built-in method that we can use to retrieve a key from our dictionary using its value. However, using other features of the language, we can create methods to perform this task. In this article, let’s implement and discuss several methods that we can utilize to get a dictionary key by value.

When we are done exploring these methods, we’ll perform a benchmark test to determine the fastest way to accomplish this task.

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

Let’s dive in.

Support Code Maze on Patreon to get rid of ads and get the best discounts on our products!
Become a patron at Patreon!

How To Retrieve a Dictionary Key by Value in C#

In this section, we will take a look at four different methods for performing a reverse dictionary lookup:

Now, let’s note an important caveat before we implement our methods. In C#, dictionary keys must be unique. This means that we can’t add the same key to our dictionary twice. However, this constraint does not apply to the values in our dictionary. We can have the same value for multiple keys.

Therefore, when trying to retrieve a key via a value from a dictionary, there is a possibility that we will encounter multiple keys for that value.

In this article, we will focus on retrieving the first key corresponding to the given value. For cases where we may likely have duplicate values, we can modify the methods we will define here to capture all the corresponding keys in a collection.

With that, let’s now proceed to creating our methods.

Get a Dictionary Key by Value With a Reverse Dictionary

When we first encounter this task, a quick solution we might consider is to immediately create another dictionary that has the values from our original dictionary as keys and the keys as values. Then, with our original values as keys in this new dictionary, we invoke the TryGetValue() method to retrieve the desired key.

This approach is feasible, so let’s implement a method that does this:

public string? UseReverseDictionary()
{
    var reverseDict = new Dictionary<string, string>();
    foreach (var keyValuePair in dict)
    {
        reverseDict.TryAdd(keyValuePair.Value, keyValuePair.Key);
    }

    reverseDict.TryGetValue(value, out var key);

    return key;
}

First, we create a Dictionary<TKey, TValue> object. Then, we iterate through the key-value pairs, adding our original values as keys and the keys as values. Using the TryAdd() method ensures that the addition process goes smoothly without any exceptions when we try to add duplicate keys. If we attempt to add a duplicate key, TryAdd() returns false without modifying the dictionary, and we proceed to the next KeyValuePair.

After that, we call the TryGetValue() method on our reverse dictionary to retrieve the key associated with the specified value. If we find this value in the dictionary, we store its key in the out parameter, key. Otherwise, we store the default value for strings (null) in the key argument. Lastly, we return the key value.

Using a Reverse Lookup

Next up, let’s explore an alternate way of reversing our dictionary:

public string? UseReverseLookup()
{
    var reverseLookup = dict.ToLookup(x => x.Value, x => x.Key);

    return reverseLookup[value].FirstOrDefault();
}

Here, we invoke the ToLookup() LINQ extension method on our dictionary. We instruct it to take the values and keys from our input dictionary and enter them as keys and values respectively in a new Lookup<TKey, TElement> instance.

A Lookup is similar to a Dictionary in that it stores keys and their associated values. However, unlike Dictionary objects, a Lookup can map a single key to a collection of values.

Now, after creating our Lookup, we access the collection of keys mapped to our input value and return the first key or null if the value does not exist.

Retrieve a Dictionary Key by Looping Through the KeyValuePairs

Moving forward, let’s see how to get this task done by iterating through the key-value pairs in our dictionary:

public string? LoopThroughKeyValuePairs()
{
    foreach (var keyValuePair in dict)
    {
        if (keyValuePair.Value == value)
        {
            return keyValuePair.Key;
        }
    }

    return default;
}

In our foreach loop, we go through all the pairs in our dictionary searching for any value that matches our input value. Once we find a match, we return its key.

If we don’t find a matching value at the end of our loop iteration, we return the default value for strings.

Iterate Over the Keys in the Dictionary

Similarly, we can iterate over the keys in our dictionary:

public string? LoopThroughKeys()
{
    foreach (var key in dict.Keys)
    {
        if (dict[key] == value)
        {
            return key;
        }
    }

    return default;
}

In this case, we use each key as an indexer to find a value that is the same as our input value. If any key’s value matches, we return the key. Otherwise, we return default. 

Benchmarking the Methods

Now, it’s time to benchmark these methods. We will use the BenchmarkDotNet package to carry out this benchmark. If you aren’t familiar with this package and want to learn how to benchmark methods with it, kindly visit our introduction to benchmarking C# projects.

To ensure the accuracy of the inferences we make from our benchmark, we will run it with a dictionary containing 100000 items and attempt to retrieve the key of a non-existent value. Attempting to retrieve the key of an existing value in our benchmark may produce skewed results, as we cannot guarantee the ordering of pairs in our dictionary.

In such scenarios, the value we aim to retrieve might be the first item in our dictionary, and we will obtain it quickly. By searching for a non-existent value, we simulate the worst-case scenario in which all our methods must go through every item in our dictionary to retrieve the desired key.

Benchmark Result

To see our benchmark class implementation, please visit the source code.

Now, let’s check the benchmark results:

| Method                      | Mean        | Gen0      | Gen1      | Gen2     | Allocated  |
|---------------------------- |------------:|----------:|----------:|---------:|-----------:|
| LoopThroughTheKeyValuePairs |    538.3 us |         - |         - |        - |          - |
| LoopThroughTheKeys          |  2,993.8 us |         - |         - |        - |        2 B |
| UseReverseDictionary        |  6,480.5 us |  679.6875 |  609.3750 | 609.3750 |  8452816 B |
| UseReverseLookup            | 41,380.2 us | 1750.0000 | 1166.6667 | 333.3333 | 10897725 B |

As we can see from the benchmark results, the fastest way to get a dictionary key by value in C# is by iterating over the key-value pairs in the dictionary. This method also provides the extra advantage of avoiding additional memory allocation and thus potential garbage collection.

After that, the second-fastest way to carry out this task is by iterating over the keys in the dictionary. This approach consumes a small amount of memory and takes about 5x the time required to execute the first method.

Following these methods, we see the method that manually reverses our dictionary. With this method, we experience the second-highest execution time and garbage collection rate due to the significant amount of managed memory it allocates (basically duplicating our original dictionary).

Finally, the slowest way to get a dictionary key by value in C# is by invoking the ToLookup() method to reverse our dictionary. This method consumes the most memory and uses the garbage collector more frequently. This is because we create many keys and their corresponding collection values for each Lookup object.

Conclusion

In this article, we created and discussed four methods to get a dictionary key by value. We then benchmarked our methods. Through this, we discovered that the fastest way to find a dictionary key by value is by iterating over the key-value pairs in our dictionary.

Liked it? Take a second to support Code Maze on Patreon and get the ad free reading experience!
Become a patron at Patreon!