.net 如何遍历 Dictionary 并更改值?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2260446/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-03 13:54:48  来源:igfitidea点击:

How to iterate through Dictionary and change values?

.netdictionaryc#-3.0

提问by Sergey

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

I get an error: "Property or indexer 'System.Collections.Generic.KeyValuePair.Value' cannot be assigned to -- it is read only."
How can I iterate through myDictand change values?

我收到错误消息:“无法将属性或索引器 'System.Collections.Generic.KeyValuePair.Value' 分配给 - 它是只读的。”
如何遍历myDict和更改值?

回答by Justin R.

According to MSDN:

根据MSDN

The foreach statement is a wrapper around the enumerator, which allows only reading from the collection, not writing to it.

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

Use this:

用这个:

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

回答by NielsSchroyen

For the lazy programmers:

对于懒惰的程序员:

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

回答by Ron Klein

You shouldn't change the dictionary while iterating it, otherwise you get an exception.

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

So first copy the key-value pairs to a temp list and then iterate through this temp list and then change your dictionary:

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

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

output (on my machine):

输出(在我的机器上):

a = 2.2
b = 77777.333
c = 2.346

a = 2.2
b = 77777.333
c = 2.346

Note: in terms of performance, this solution is a bit better than currently posted solutions, since the value is already assigned with the key, and there's no need to fetch it again from the dictionary object.

注意:在性能方面,此解决方案比当前发布的解决方案要好一些,因为该值已分配给键,无需再次从字典对象中获取它。

回答by Risord

I noticed that fastest way (at this moment) iterate over Dictionary with modify is:

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

//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

VS

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

First one takes about 2.2s and second one 4.5s (tested dictionary size of 1000 and repeated 10k time, changing dictionary size to 10 didn't change the ratios). Also there wasn't a big deal with getting the Key list, dictionary[key] value get is just slow VS built in iteration. Also if you want even more speed use hard coded type to dumb ("Test") class, with that I got it about 1.85s (with hard coded to "object").

第一个需要大约 2.2 秒,第二个需要 4.5 秒(测试字典大小为 1000 并重复 10k 次,将字典大小更改为 10 并没有改变比率)。获取 Key 列表也没什么大不了的,dictionary[key] value get 只是迭代中内置的缓慢 VS。另外,如果你想要更快的速度,使用硬编码类型到哑(“测试”)类,我得到了大约 1.85 秒(硬编码为“对象”)。

EDIT:

编辑:

Anna has posted the same solution before: https://stackoverflow.com/a/6515474/766304

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

回答by user3104267

passed some time, but maybe someone is interested in it:

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

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

回答by Hypno

One solution would be to put the keys in a list (or another collection) beforehand and iterate through them while changing the dictionary:

一种解决方案是预先将键放入列表(或另一个集合)中,并在更改字典时迭代它们:

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

回答by Desty

While iterating over the dictionary directly is not possible because you get an exception (like Ron already said), you don't need to use a temp list to solve the problem.

虽然直接迭代字典是不可能的,因为您会遇到异常(就像 Ron 已经说过的那样),但您不需要使用临时列表来解决问题。

Instead use not the foreach, but a forloop to iterate through the dictionary and change the values with indexed access:

而不是使用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);
}

回答by Michael Petrotta

Loop through the keys in the dictionary, not the KeyValuePairs.

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

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