Как перебирать словарь и изменять значения?
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
и изменять значения?
Ответы
Ответ 1
Согласно 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);
}
Ответ 2
Для ленивых программистов:
Dictionary<string, double> dictionary = new Dictionary<string, double>();
foreach (var key in dictionary.Keys.ToList())
{
dictionary[key] = Math.Round(dictionary[key], 3);
}
Ответ 3
Вы не должны менять словарь во время его итерации, иначе вы получите исключение.
Итак, сначала скопируйте пары ключ-значение в список тем, затем перейдите в этот список тем и затем измените словарь:
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
Примечание: с точки зрения производительности это решение немного лучше, чем в настоящее время размещенные решения, поскольку значение уже назначено ключом, и нет необходимости извлекать его снова из объекта словаря.
Ответ 4
Одним из решений было бы поместить ключи в список (или другую коллекцию) заранее и перебрать их при смене словаря:
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);
}
Ответ 5
Я заметил, что самый быстрый способ (в данный момент) повторить использование словаря с модификацией:
//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] get просто медленное VS, построенное на итерации. Кроме того, если вы хотите, чтобы еще более высокая скорость использовала жесткий кодированный тип для немого ( "Test" ) класса, с этим я получил его около 1,85 с (с жестко закодированным до "объекта" ).
EDIT:
Анна отправила такое же решение раньше: fooobar.com/questions/98363/...
Ответ 6
прошло некоторое время, но, возможно, кто-то заинтересован в этом:
yourDict = yourDict.ToDictionary(kv => kv.Key, kv => Math.Round(kv.Value, 3))
Ответ 7
Итерация по словарю напрямую невозможна, потому что вы получаете исключение (как уже сказал 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);
}
Ответ 8
Прокручивайте ключи в словаре, а не KeyValuePairs.
Dictionary<string, double> myDict = new Dictionary<string, double>();
//...
foreach (string key in myDict.Keys)
{
myDict[key] = Math.Round(myDict[key], 3);
}