开发者

Best way to change dictionary key

开发者 https://www.devze.com 2023-03-15 23:41 出处:网络
I am wondering is there a better way to change a dictionary key, for example: var dic = new Dictionary<string, int>();

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 开发者_JAVA技巧just rename the key rather than add a new key value pair of ("b",1) and then remove "a" ?


No, you cannot rename keys once that have been added to a Dictionary. If you want a rename facility, perhaps add your own extension method:

public static void RenameKey<TKey, TValue>(this IDictionary<TKey, TValue> dic,
                                      TKey fromKey, TKey toKey)
{
  TValue value = dic[fromKey];
  dic.Remove(fromKey);
  dic[toKey] = value;
}


The Dictionary in c# is implemented as a hashtable. Therefore, if you were able to change the key via some Dictionary.ChangeKey method, the entry would have to be re-hashed. So it's not really any different (aside from convenience) than removing the entry, and then adding it again with the new key.


public static bool ChangeKey<TKey, TValue>(this IDictionary<TKey, TValue> dict, 
                                           TKey oldKey, TKey newKey)
{
    TValue value;
    if (!dict.TryGetValue(oldKey, out value))
        return false;

    dict.Remove(oldKey);
    dict[newKey] = value;  // or dict.Add(newKey, value) depending on ur comfort
    return true;
}

Same as Colin's answer, but doesn't throw exception, instead returns false on failure. In fact I'm of the opinion that such a method should be default in dictionary class considering that editing the key value is dangerous, so the class itself should give us an option to be safe.


Starting with .NET Core, this is more efficient:

public static bool ChangeKey<TKey, TValue>(this IDictionary<TKey, TValue> dict, 
                                           TKey oldKey, TKey newKey)
{
    TValue value;
    if (!dict.Remove(oldKey, out value))
        return false;

    dict[newKey] = value;  // or dict.Add(newKey, value) depending on ur comfort
    return true;
}


Do you like this simple code?

var newDictionary= oldDictionary.ReplaceInKeys<object>("_","-");

It replace '_' with '-' in all keys


If

  • type of your key is string

and

  • you want replace a string with other string in all keys of the dictionary

then use my way


You just need to add the following class to your app:

public static class DicExtensions{

    public static void ReplaceInKeys<TValue>(this IDictionary<string, TValue> oldDictionary, string replaceIt, string withIt)
    {
          // Do all the works with just one line of code:
          return oldDictionary
                 .Select(x=> new KeyValuePair<string, TValue>(x.Key.Replace(replaceIt, withIt), x.Value))
                 .ToDictionary(x=> x.Key,x=> x.Value);
    }
}

I use Linq to change my dictionary keys (regenerate a dictionary by linq)

The magic step is ToDictionary() method.


Note: We can make an advanced Select include a block of codes for complicated cases instead of a simple lambda.

Select(item =>{
            .....Write your Logic Codes Here....

            return resultKeyValuePair;
       })


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.


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);


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}.");
}
0

精彩评论

暂无评论...
验证码 换一张
取 消