Reputation: 49728
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 myDict
and change values?
Upvotes: 83
Views: 88342
Reputation: 190
passed some time, but maybe someone is interested in it:
yourDict = yourDict.ToDictionary(kv => kv.Key, kv => Math.Round(kv.Value, 3))
Upvotes: 6
Reputation: 24021
According to MSDN:
The foreach statement is a wrapper around the enumerator, which allows only reading from the collection, not writing to it.
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);
}
Upvotes: 120
Reputation: 11
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);
}
Upvotes: 1
Reputation: 2196
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
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").
EDIT:
Anna has posted the same solution before: https://stackoverflow.com/a/6515474/766304
Upvotes: 3
Reputation: 60902
Loop through the keys in the dictionary, not the KeyValuePairs.
Dictionary<string, double> myDict = new Dictionary<string, double>();
//...
foreach (string key in myDict.Keys)
{
myDict[key] = Math.Round(myDict[key], 3);
}
Upvotes: -3
Reputation: 449
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);
}
Upvotes: 43
Reputation: 2776
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.
Instead use not the foreach
, but a for
loop to iterate through the dictionary and change the values with indexed access:
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);
}
Upvotes: -1
Reputation: 9440
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
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.
Upvotes: 7