Come scorrere il dizionario e modificare i valori?

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

Viene visualizzato un messaggio di errore: “Imansible assegnare la proprietà o l’indicizzatore ‘System.Collections.Generic.KeyValuePair.Value’ – è di sola lettura.”
Come posso eseguire iterate su myDict e modificare i valori?

Secondo MSDN :

L’istruzione foreach è un wrapper attorno all’enumeratore, che consente solo la lettura dalla raccolta, non la scrittura.

Usa questo:

 var dictionary = new Dictionary(); // TODO Populate your dictionary here var keys = new List(dictionary.Keys); foreach (string key in keys) { dictionary[key] = Math.Round(dictionary[key], 3); } 

Per i programmatori pigri:

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

Non dovresti cambiare il dizionario mentre lo itera, altrimenti ottieni un’eccezione.

Quindi, prima copia le coppie chiave-valore in una lista temporanea e poi itera su questa lista temporanea e poi cambia il dizionario:

 Dictionary myDict = new Dictionary(); // a few values to play with myDict["a"] = 2.200001; myDict["b"] = 77777.3333; myDict["c"] = 2.3459999999; // prepare the temp list List> list = new List>(myDict); // iterate through the list and then change the dictionary object foreach (KeyValuePair 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(); 

uscita (sulla mia macchina):

a = 2.2
b = 77777.333
c = 2.346

Nota : in termini di prestazioni, questa soluzione è leggermente migliore rispetto alle soluzioni attualmente pubblicate, poiché il valore è già assegnato con la chiave e non è necessario recuperarlo nuovamente dall’object del dizionario.

Ho notato che il modo più veloce (in questo momento) iterare su Dizionario con modifica è:

 //Just a dumb class class Test { public T value; public Test() { } public Test(T v) { value = v; } } Dictionary> dic = new Dictionary>(); //Init dictionary foreach (KeyValuePair pair in dic) { pair.Value.value = TheObject;//Modify } 

VS

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

Il primo richiede circa 2.2 secondi e il secondo 4.5 secondi (dimensione del dizionario testata di 1000 e tempo di ripetizione di 10k, la modifica della dimensione del dizionario a 10 non ha modificato i rapporti). Inoltre non c’è stato un grosso problema con l’ottenimento dell’elenco di chiavi, il valore di [key] del dizionario è solo lento VS incorporato nell’iterazione. Inoltre, se vuoi ancora più velocità usa il tipo hard coded in “dumb” (“Test”), con cui ho ottenuto circa 1.85s (con hard coded to “object”).

MODIFICARE:

Anna ha pubblicato la stessa soluzione prima: https://stackoverflow.com/a/6515474/766304

Una soluzione potrebbe essere quella di mettere le chiavi in ​​una lista (o un’altra raccolta) in anticipo e iterare attraverso di esse mentre si cambia il dizionario:

 Dictionary dictionary = new Dictionary(); // Populate it List keys = new List(dictionary.Keys); foreach (string key in keys) { dictionary[key] = Math.Round(dictionary[key], 3); } 

passato un po ‘di tempo, ma forse qualcuno è interessato a questo:

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

Non è ansible eseguire iterazioni direttamente sul dizionario perché si ottiene un’eccezione (come già detto Ron), non è necessario utilizzare un elenco temporaneo per risolvere il problema.

Usa invece non il foreach , ma un ciclo for per scorrere il dizionario e modificare i valori con accesso indicizzato:

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

Passa in rassegna le chiavi nel dizionario, non in KeyValuePairs.

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