Подтвердить что ты не робот

Как перебирать словарь и изменять значения?

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 и изменять значения?

4b9b3361

Ответ 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);
}