Best way to change dictionary key

Viewed 72447

I am wondering is there a better way to change a dictionary key, for example:

var dic = new Dictionary<string, int>();
dic.Add("a", 1);

and later on I decided to make key value pair to be ("b" , 1) , is it possible to just rename the key rather than add a new key value pair of ("b",1) and then remove "a" ?

Thanks in advance.

7 Answers

Dictionary KeyValuePair's in C# maintain their order until a entry is removed. All keys following a removed key's position are then shifted up one position.

You can, however, use Linq and an Extension Method to make an expensive, yet versatile function that renames your key, and maintains the order and value references.

I want to reiterate that this is very expensive and should not be used inside a loop. Use this when infrequent renaming is required.

using System.Linq;

public static class DictionaryExtensions
{
    ///<Summary> A relatively expensive operation to rename keys</Summary>
    public static void RenameKey<TKey, TValue>(this Dictionary<TKey, TValue> dict, TKey from, TKey to)
    {                  
        Dictionary<TKey, TValue>  temp = new Dictionary<TKey, TValue>(dict);
        dict.Clear();
        for(int i = 0; i < temp.Count; i++)
        {
            var kvp = temp.ElementAt(i);

            if(kvp.Key.Equals(from))
                dict.Add(to, temp[from]);
            else 
                dict.Add(kvp.Key, kvp.Value);
        }
    }
}

Usage:

dict.RenameKey(oldName, newName);

Easy way to achieve the outcome of changing the keys (if you need to do it in bulk) is by projecting a new dictionary using System.Linq:

var rehashedDictionary = existingDictionary.ToDictionary(kvp => $"newkey-{kvp.Key}", kvp => kvp.Value);

If you are dealing with large collections you may want to use something more specialized for performance.

Similar to nawfal's answer, with the difference that the key is changed only if both conditions are true:

  1. The old key exists.
  2. The new key does not exist.
/// <summary>Attempts to change the key of a value in the dictionary.</summary>
public static bool TryChangeKey<TKey, TValue>(
    this Dictionary<TKey, TValue> source, TKey oldKey, TKey newKey, out TValue value)
{
    if (source.ContainsKey(newKey)) { value = default; return false; }
    if (!source.Remove(oldKey, out value)) return false;
    source.Add(newKey, value);
    return true;
}

Usage:

if (myDictionary.TryChangeKey(oldKey, newKey, out var value))
{
    Console.WriteLine($"Key of {value} changed from {oldKey} to {newKey}.");
}
Related