如何遍历Dictionary并更改值?

Ser*_*gey 68 .net dictionary c#-3.0

Dictionary<string,double> myDict = new Dictionary();
//...
foreach (KeyValuePair<string,double> kvp in myDict)
 {
     kvp.Value = Math.Round(kvp.Value, 3);
}
Run Code Online (Sandbox Code Playgroud)

我收到一个错误:"无法将属性或索引器'System.Collections.Generic.KeyValuePair.Value'分配给它 - 它是只读的."
如何迭代myDict并更改值?

Jus*_* R. 100

根据MSDN:

foreach语句是枚举器的包装器,它只允许从集合中读取,而不是写入它.

用这个:

var dictionary = new Dictionary<string, double>();
// TODO Populate your dictionary here
var keys = new List<string>(dictionary.Keys);
foreach (string key in keys)
{
   dictionary[key] = Math.Round(dictionary[key], 3);
}
Run Code Online (Sandbox Code Playgroud)

  • 我在.NET 2和3.5中测试了你的例子,它抛出了'Collection was modified exception'.请参阅:http://stackoverflow.com/questions/1562729/why-cant-we-change-values-of-a-dictionary-while-enumerating-its-keys这在.NET 4中是否已更改,或者您是否未测试过例? (6认同)
  • 多么尴尬 - 我遗漏了填充列表的部分.现在修复了.这里的想法是你可以改变字典条目的值,而不是它的引用. (2认同)

小智 34

对于懒惰的程序员:

Dictionary<string, double> dictionary = new Dictionary<string, double>();
foreach (var key in dictionary.Keys.ToList())
{
   dictionary[key] = Math.Round(dictionary[key], 3);
}
Run Code Online (Sandbox Code Playgroud)

  • 我知道这是一个古老的答案,但我更喜欢它接受的 - 我会说而不是懒惰它更简洁(删除明确声明键列表的行).因此,要回答上面的问题:您可以枚举密钥集合,但问题是枚举和进行更改,这是您无法做到的.添加ToList()意味着您实际上枚举的列表恰好包含与字典中的键相同的对象.这使得字典本身变得可变,因此允许您进行更改. (6认同)
  • @MikeC在http://stackoverflow.com/a/2260462/1037948上看到评论 - 你不能直接枚举键,`.ToList()`是一个"黑客"来解决这个问题 (4认同)
  • ToList()是LINQ扩展方法.如果添加"using System.Linq;",它应该可用.你的使用陈述. (3认同)
  • 正如我现在使用.NET 4.5编写的那样,`ToList()`方法不可用,但`Keys`成员是可迭代的,所以`.ToList()`是不必要的. (2认同)

Ron*_*ein 8

在迭代时不应该更改字典,否则会出现异常.

首先将键值对复制到临时列表,然后遍历此临时列表,然后更改字典:

Dictionary<string, double> myDict = new Dictionary<string, double>();

// a few values to play with
myDict["a"] = 2.200001;
myDict["b"] = 77777.3333;
myDict["c"] = 2.3459999999;

// prepare the temp list
List<KeyValuePair<string, double>> list = new List<KeyValuePair<string, double>>(myDict);

// iterate through the list and then change the dictionary object
foreach (KeyValuePair<string, double> kvp in list)
{
    myDict[kvp.Key] = Math.Round(kvp.Value, 3);
}


// print the output
foreach (var pair in myDict)
{
    Console.WriteLine(pair.Key + " = " + pair.Value);
}

// uncomment if needed
// Console.ReadLine();
Run Code Online (Sandbox Code Playgroud)

输出(在我的机器上):

a = 2.2
b = 77777.333
c = 2.346

注意:就性能而言,此解决方案比当前发布的解决方案稍好一些,因为该值已经使用密钥分配,并且无需再次从字典对象中获取它.


use*_*267 6

已经有一段时间了,但也许有人对此感兴趣:

yourDict = yourDict.ToDictionary(kv => kv.Key, kv => Math.Round(kv.Value, 3))
Run Code Online (Sandbox Code Playgroud)