如何在 C# 中更新存储在 Dictionary 中的值?

Posted

技术标签:

【中文标题】如何在 C# 中更新存储在 Dictionary 中的值?【英文标题】:How to update the value stored in Dictionary in C#? 【发布时间】:2010-11-17 15:22:45 【问题描述】:

如何更新字典 Dictionary<string, int> 中特定键的值?

【问题讨论】:

我有一个复杂类型存储为字典中的值。当我想更改存储值的属性时,我得到 CS1612。因此我必须采取一种方法: var v = dict[c]; v.dprop = c.sprop; dict[c] = v; @peter70,只有结构体,因为结构体是按值返回的,所以“更新”它们只会更新它的临时本地副本。 【参考方案1】:

只需指向给定键的字典并分配一个新值:

myDictionary[myKey] = myNewValue;

【讨论】:

所以这种简单的方法似乎也可以更好地替代众所周知的“.Add”和“.TryGetValue”方法,而无需更改值。 (?)至少,如果覆盖键并不重要,例如在不排除键在循环中多次写入的情况下。或者有人看到任何缺点吗?特别是因为 .Add 对初学者有好处,如果忘记了 if-wrapper 或 TryGetValue,它可以在测试和其他测试数据中正常工作,其中 .Add 为同一个键调用两次它会引发异常。跨度> 这个操作的有趣之处在于,它用UPSERT(key, value)转换成字典。太棒了! 正如 Pini 所说,这应该是问题的答案。由于正确的事情并改变它。 @Philm,一个巨大的缺点是,这种方法被视为修改整个字典,换句话说,它只是更新。 @greenoldman 你确定吗?为什么要修改“整个字典”?你对你在说什么有参考吗?这肯定是字典上的一个运算符,调用一个方法做的事情完全一样......【参考方案2】:

可以通过将键作为索引来访问

例如:

Dictionary<string, int> dictionary = new Dictionary<string, int>();
dictionary["test"] = 1;
dictionary["test"] += 1;
Console.WriteLine (dictionary["test"]); // will print 2

【讨论】:

如果List中没有“test”项,则list["test"] = list["test"] + 1;将引发 KeyNotFoundException!不存在的索引器的纯分配将起作用。列表[“测试”] = 1; 还能用list["test"]++;吗? 不要叫字典列表,叫它狗或猫或字典 @aufty 你可以写++dictionary["test"];dictionary["test"]++;,但前提是字典中有一个键值为“test”的条目——例如:if(dictionary.ContainsKey("test")) ++dictionary["test"];else dictionary["test"] = 1; // create entry with key "test"【参考方案3】:

你可以按照这个方法:

void addOrUpdate(Dictionary<int, int> dic, int key, int newValue)

    int val;
    if (dic.TryGetValue(key, out val))
    
        // yay, value exists!
        dic[key] = val + newValue;
    
    else
    
        // darn, lets add the value
        dic.Add(key, newValue);
    

您在这里获得的优势是您只需 1 次访问字典即可检查并获取相应键的值。 如果您使用ContainsKey 检查存在并使用dic[key] = val + newValue; 更新值,那么您将访问字典两次。

【讨论】:

你可以使用dic[key] = newvalue;代替dic.Add(key, newValue); 如果你执行“dic[key] = value”并且“key”不存在会怎样? @superpuccio 你得到一个 KeyNotFoundException @ntroncos 不正确,它将使用提供的值将该键添加到字典中。 += 不适用于不存在的键,因为它只是 dic[key] = value + dic[key] 的语法糖。 这应该是问题的答案,因为它涉及更新字典而不仅仅是添加字典。【参考方案4】:

使用 LINQ:访问字典的键并更改值

Dictionary<string, int> dict = new Dictionary<string, int>();
dict = dict.ToDictionary(kvp => kvp.Key, kvp => kvp.Value + 1);

【讨论】:

我什至不明白它是如何工作的,但它很棒 为这么简单的事情创建另一本字典对我来说没有意义。检查 ccalboni 的答案。 我认为这是一个很好的答案。它不需要你知道每个键字符串 第二行(LINQ 语句)每次都会创建整个字典的副本。不是一个好主意。【参考方案5】:

这是一种通过索引进行更新的方法,类似于foo[x] = 9,其中x 是键,9 是值

var views = new Dictionary<string, bool>();

foreach (var g in grantMasks)

    string m = g.ToString();
    for (int i = 0; i <= m.Length; i++)
    
        views[views.ElementAt(i).Key] = m[i].Equals('1') ? true : false;
    

【讨论】:

m[i].Equals('1') 已经计算为布尔值,所以添加 ? true : false 是不必要的 我不知道这个逻辑有多高效,但我喜欢 For 循环的想法。 :)【参考方案6】:

    update - 只修改存在的。为避免使用索引器的副作用:

    int val;
    if (dic.TryGetValue(key, out val))
    
        // key exist
        dic[key] = val;
    
    

    更新或(如果 dic 中不存在值,则添加新)

    dic[key] = val;
    

    例如:

    d["Two"] = 2; // adds to dictionary because "two" not already present
    d["Two"] = 22; // updates dictionary because "two" is now present
    

【讨论】:

【参考方案7】:

这个简单的检查将执行更新或创建。

if(!dictionary.TryAdd(key, val))

    dictionary[key] = val;

【讨论】:

为什么不干脆做dictionary[key] = value;这将直接更新值。 请注意,这个答案是关于 upsert,即更新或创建。而不是简单地更新。 @Deb【参考方案8】:

这可能对你有用:

场景 1:原始类型

string keyToMatchInDict = "x";
int newValToAdd = 1;
Dictionary<string,int> dictToUpdate = new Dictionary<string,int>"x",1;

if(!dictToUpdate.ContainsKey(keyToMatchInDict))
   dictToUpdate.Add(keyToMatchInDict ,newValToAdd );
else
   dictToUpdate[keyToMatchInDict] = newValToAdd; //or you can do operations such as ...dictToUpdate[keyToMatchInDict] += newValToAdd;

场景 2:我用于 List as Value 的方法

int keyToMatch = 1;
AnyObject objInValueListToAdd = new AnyObject("something for the Ctor")
Dictionary<int,List<AnyObject> dictToUpdate = new Dictionary<int,List<AnyObject>(); //imagine this dict got initialized before with valid Keys and Values...

if(!dictToUpdate.ContainsKey(keyToMatch))
   dictToUpdate.Add(keyToMatch,new List<AnyObject>objInValueListToAdd);
else
   dictToUpdate[keyToMatch] = objInValueListToAdd;

希望对需要帮助的人有用。

【讨论】:

【参考方案9】:

此扩展方法允许匹配谓词委托作为字典键选择器,并允许单独的委托执行字典值替换,因此对于所使用的键/值对的类型是完全开放的:

public static void UpdateAll<TKey, TValue>(this IDictionary<TKey, TValue> dictionary, Func<TKey, TValue, bool> matchPredicate, Func<TValue, TValue> updatePredicate)

  var keys = dictionary.Keys.Where(k => matchPredicate(k, dictionary[k])).ToList();
  foreach (var key in keys)
  
    dictionary[key] = updatePredicate(dictionary[key]);
  

示例用法:

    Dictionary<int, string> dict = new Dictionary<int, string>();
    dict.Add(1, "One");
    dict.Add(2, "Two");
    dict.Add(3, "Three");

    //Before
    foreach(var kvp in dict)
      Console.WriteLine(kvp.Value);
    

    dict.UpdateAll(
        matchPredicate: (k, v) => k >= 2, //Update any dictionary value where the key is >= 2
        updatePredicate: (v) => v = v + " is greater than One"
      );

    //After
    foreach(var kvp in dict)
      Console.WriteLine(kvp.Value);
    

【讨论】:

以上是关于如何在 C# 中更新存储在 Dictionary 中的值?的主要内容,如果未能解决你的问题,请参考以下文章

在 C# 中枚举到字典

C# Hashtable和Dictionary区别

C#创建安全的字典(Dictionary)存储结构

C# 存储相同键多个值的Dictionary

如何在 C# 中将 Dictionary<string, object> 转换为 Dictionary<string, string>

C#日常C#集合Dictionary获取第一个键值