如何遍历Dictionary并更改值?

时间:2010-02-14 07:39:54

标签: .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);
}

我收到错误: “无法将属性或索引器'System.Collections.Generic.KeyValuePair.Value'分配给 - 它是只读的。”

如何迭代myDict并更改值?

8 个答案:

答案 0 :(得分:97)

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

答案 1 :(得分:33)

对于懒惰的程序员:

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

答案 2 :(得分: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();

输出(在我的机器上):

  

a = 2.2
  b = 77777.333
  c = 2.346

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

答案 3 :(得分:1)

一种解决方案是事先将密钥放入列表(或其他集合)中,并在更改字典时迭代它们:

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

// Populate it
List<string> keys = new List<string>(dictionary.Keys);

foreach (string key in keys)
{
   dictionary[key] = Math.Round(dictionary[key], 3);
}

答案 4 :(得分:1)

我注意到最快的方式(此时)通过修改迭代字典:

//Just a dumb class
class Test<T>
{
    public T value;

    public Test() { }
    public Test(T v) { value = v; }
}

Dictionary<int, Test<object>> dic = new Dictionary<int, Test<object>>();
//Init dictionary
foreach (KeyValuePair<int, Test> pair in dic)
{
    pair.Value.value = TheObject;//Modify
}

VS

List<int> keys = new List<int>(dic.Keys); //This is fast operation   
foreach (int key in keys)
{
    dic[key] = TheObject;
}

第一个需要大约2.2秒,第二个需要4.5秒(测试字典大小为1000并重复10k时间,将字典大小更改为10不会改变比率)。获得密钥列表也没什么大不了的,字典[key]值得到的只是缓慢的VS内置迭代。此外,如果你想要更快的速度使用硬编码类型愚蠢(“测试”)类,我得到它约1.85s(硬编码为“对象”)。

修改

Anna之前发布过相同的解决方案:https://stackoverflow.com/a/6515474/766304

答案 5 :(得分:1)

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

yourDict = yourDict.ToDictionary(kv => kv.Key, kv => Math.Round(kv.Value, 3))

答案 6 :(得分:-1)

虽然直接迭代字典是不可能的,因为你得到了一个例外(比如Ron已经说过),你不需要使用临时列表来解决问题。

而不是使用foreach,而是使用for循环遍历字典并使用索引访问权限更改值:

Dictionary<string, double> myDict = new Dictionary<string,double>();
//...    
for(int i = 0; i < myDict.Count; i++) {
    myDict[myDict.ElementAt(i).Key] = Math.Round(myDict.ElementAt(i).Value, 3);
}

答案 7 :(得分:-2)

循环遍历字典中的键,而不是KeyValuePairs。

Dictionary<string, double> myDict = new Dictionary<string, double>();
//...
foreach (string key in myDict.Keys)
{
    myDict[key] = Math.Round(myDict[key], 3);
}