更改字典关键字的最佳方式

本文关键字:最佳 方式 关键字 字典 | 更新日期: 2023-09-27 18:00:36

我想知道有没有更好的方法来更改字典键,例如:

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

后来我决定将键值对设为("b",1),是否可以只重命名键,而不是添加一个新的键值对("b",1)然后删除"b";a"?

更改字典关键字的最佳方式

不,一旦添加到字典中,就不能重命名键。如果你想要一个重命名工具,也许可以添加你自己的扩展方法:

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

c#中的Dictionary被实现为哈希表。因此,如果您能够通过某种Dictionary.ChangeKey方法更改密钥,则必须对条目进行重新散列。因此,这与删除条目,然后用新密钥再次添加条目没有什么不同(除了方便之外)。

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

与Colin的回答相同,但没有抛出异常,而是在失败时返回false。事实上,考虑到编辑键值是危险的,我认为字典类中应该默认这样的方法,所以类本身应该给我们一个安全的选项。


从开始。NET核心,这更有效:

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

你喜欢这个简单的代码吗

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

它将所有密钥中的'_'替换为'-'


如果

  • 您的key类型为string

  • 您希望在字典的所有键中将字符串替换为其他字符串

然后使用我的方式


你只需要将以下类添加到你的应用程序中:

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

我使用Linq更改字典键(通过linq重新生成字典)

神奇的步骤是ToDictionary()方法。


注意:我们可以使高级选择包含用于复杂情况的代码块,而不是简单的lambda。

Select(item =>{
            .....Write your Logic Codes Here....
            return resultKeyValuePair;
       })

实现更改键结果的简单方法(如果需要批量更改)是使用System投影一个新字典。Linq:

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

如果您正在处理大型集合,您可能希望使用更专业的性能。

C#中的字典KeyValuePair保持它们的顺序,直到删除一个条目。移除的钥匙位置之后的所有钥匙都会向上移动一个位置。

但是,您可以使用Linq和扩展方法来生成一个昂贵的但通用的函数,该函数可以重命名键,并维护顺序和值引用。

我想重申,这是非常昂贵的,并且不应该在循环中使用。当需要不频繁的重命名时,请使用此选项。

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

用法:

dict.RenameKey(oldName, newName);

类似于nawfal的答案,不同之处在于只有当两个条件都为真时才更改密钥:

  1. 旧密钥存在
  2. 新密钥不存在
/// <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;
}

用法:

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