Dictionary<string,double> myDict = new Dictionary();
//...
foreach (KeyValuePair<string,double> kvp in myDict)
{
kvp.Value = Math.Round(kvp.Value, 3);
}
Ich erhalte die Fehlermeldung: "Eigenschaft oder Indexer 'System.Collections.Generic.KeyValuePair.Value' kann nicht zugewiesen werden - es ist schreibgeschützt."
Wie kann ich myDict
Werte durchlaufen und ändern?
.net
dictionary
c#-3.0
Sergey
quelle
quelle
class Box<T> { public T boxed; }
Und dann ein verwenden,Dictionary<string, Box<double>>
das Sie dann verwenden können "modifizieren" im foreach so etwas wie :kvp.Value.boxed = 123.456;
. Nicht zu sagen, dass es der "beste" Ansatz ist, aber es hat seinen Anteil an Verwendungen.Antworten:
Laut MSDN :
Benutze das:
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); }
quelle
Für die faulen Programmierer:
Dictionary<string, double> dictionary = new Dictionary<string, double>(); foreach (var key in dictionary.Keys.ToList()) { dictionary[key] = Math.Round(dictionary[key], 3); }
quelle
ToList()
Methode nicht verfügbar, aber dasKeys
Mitglied ist iterierbar und daher.ToList()
nicht erforderlich ..ToList()
ist ein "Hack", um das zuSie sollten das Wörterbuch nicht ändern, während Sie es wiederholen, da sonst eine Ausnahme auftritt.
Kopieren Sie also zuerst die Schlüssel-Wert-Paare in eine temporäre Liste, durchlaufen Sie diese temporäre Liste und ändern Sie dann Ihr Wörterbuch:
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();
Ausgabe (auf meinem Computer):
Hinweis : In Bezug auf die Leistung ist diese Lösung etwas besser als derzeit veröffentlichte Lösungen, da der Wert bereits mit dem Schlüssel zugewiesen wurde und nicht erneut aus dem Wörterbuchobjekt abgerufen werden muss.
quelle
einige Zeit vergangen, aber vielleicht interessiert sich jemand dafür:
yourDict = yourDict.ToDictionary(kv => kv.Key, kv => Math.Round(kv.Value, 3))
quelle
Ich habe festgestellt, dass der schnellste Weg (in diesem Moment) über das Wörterbuch mit Änderung iteriert:
//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; }
Das erste dauert ungefähr 2,2 Sekunden und das zweite 4,5 Sekunden (getestete Wörterbuchgröße von 1000 und wiederholte 10.000-malige Zeit, das Ändern der Wörterbuchgröße auf 10 hat die Verhältnisse nicht geändert). Es gab auch keine große Sache mit dem Abrufen der Schlüsselliste. Der Wert des Wörterbuchs [Schlüssel] ist nur langsam, VS in Iteration eingebaut. Auch wenn Sie noch mehr Geschwindigkeit wollen, verwenden Sie einen hartcodierten Typ für eine dumme Klasse ("Test"). Damit habe ich ungefähr 1,85 Sekunden (mit einem hartcodierten Typ für "Objekt").
BEARBEITEN:
Anna hat dieselbe Lösung bereits veröffentlicht: https://stackoverflow.com/a/6515474/766304
quelle
Eine Lösung wäre, die Schlüssel vorher in eine Liste (oder eine andere Sammlung) aufzunehmen und sie zu durchlaufen, während Sie das Wörterbuch ändern:
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); }
quelle
Während das direkte Durchlaufen des Wörterbuchs nicht möglich ist, weil Sie eine Ausnahme erhalten (wie Ron bereits sagte), müssen Sie keine temporäre Liste verwenden, um das Problem zu lösen.
Verwenden Sie stattdessen nicht die Schleife
foreach
, sondern einefor
Schleife, um das Wörterbuch zu durchlaufen und die Werte mit indiziertem Zugriff zu ändern: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); }
quelle
Enumerable.ElementAt()
handelt es sich bei der von Ihnen verwendeten Erweiterungsmethode um eineO(n)
Operation für Nicht-IList<>
Benutzer .Durchlaufen Sie die Schlüssel im Wörterbuch, nicht die KeyValuePairs.
Dictionary<string, double> myDict = new Dictionary<string, double>(); //... foreach (string key in myDict.Keys) { myDict[key] = Math.Round(myDict[key], 3); }
quelle