Ich versuche, ein Kreisdiagramm aus einem Wörterbuch zu erstellen. Bevor ich das Kreisdiagramm anzeige, möchte ich die Daten aufräumen. Ich entferne alle Kuchenstücke, die weniger als 5% des Kuchens ausmachen, und lege sie in ein "anderes" Kuchenstück. Allerdings bekomme ich Collection was modified; enumeration operation may not execute
zur Laufzeit eine Ausnahme.
Ich verstehe, warum Sie keine Elemente zu einem Wörterbuch hinzufügen oder daraus entfernen können, während Sie darüber iterieren. Ich verstehe jedoch nicht, warum Sie einen Wert für einen vorhandenen Schlüssel in der foreach-Schleife nicht einfach ändern können.
Vorschläge zur Korrektur meines Codes sind willkommen.
Dictionary<string, int> colStates = new Dictionary<string,int>();
// ...
// Some code to populate colStates dictionary
// ...
int OtherCount = 0;
foreach(string key in colStates.Keys)
{
double Percent = colStates[key] / TotalCount;
if (Percent < 0.05)
{
OtherCount += colStates[key];
colStates[key] = 0;
}
}
colStates.Add("Other", OtherCount);
Rufen Sie die
ToList()
in derforeach
Schleife. Auf diese Weise benötigen wir keine temporäre Variablenkopie. Dies hängt von Linq ab, das seit .Net 3.5 verfügbar ist.quelle
foreach(var pair in colStates.ToList())
, um den Zugriff auf den Schlüssel und den Wert zu vermeiden, wodurch vermieden werden muss, dasscolStates[key]
..Sie ändern die Sammlung in dieser Zeile:
Auf diese Weise löschen Sie an dieser Stelle im Wesentlichen etwas und fügen es wieder ein (soweit es IEnumerable betrifft.
Wenn Sie ein Mitglied bearbeiten des Wertes den Sie speichern, wäre das in Ordnung, aber Sie bearbeiten den Wert selbst und IEnumberable gefällt das nicht.
Die Lösung, die ich verwendet habe, besteht darin, die foreach-Schleife zu entfernen und nur eine for-Schleife zu verwenden. Eine einfache for-Schleife sucht nicht nach Änderungen, von denen Sie wissen, dass sie die Sammlung nicht beeinflussen.
So könnten Sie es machen:
quelle
colStates.Keys
von anstelle von bedeutenkeys
.Sie können weder die Schlüssel noch die Werte direkt in einem ForEach ändern, aber Sie können deren Mitglieder ändern. ZB sollte das funktionieren:
quelle
Wie wäre es, wenn Sie nur einige Linq-Abfragen für Ihr Wörterbuch durchführen und dann Ihr Diagramm an die Ergebnisse dieser Wörter binden? ...
quelle
Wenn Sie sich kreativ fühlen, können Sie so etwas tun. Durchlaufen Sie das Wörterbuch rückwärts, um Ihre Änderungen vorzunehmen.
Sicher nicht identisch, aber Sie könnten trotzdem interessiert sein ...
quelle
Sie müssen ein neues Wörterbuch aus dem alten erstellen, anstatt es zu ändern. Etwas wie (iterieren Sie auch über das KeyValuePair <,> anstatt eine Schlüsselsuche zu verwenden:
quelle
Beginnend mit .NET 4.5 Mit ConcurrentDictionary können Sie dies tun :
Beachten Sie jedoch, dass seine Leistung tatsächlich viel schlechter ist als eine einfache
foreach dictionary.Kes.ToArray()
:Ergebnis:
quelle
Sie können die Sammlung nicht ändern, nicht einmal die Werte. Sie können diese Fälle speichern und später entfernen. Es würde so enden:
quelle
Haftungsausschluss: Ich mache nicht viel C #
Sie versuchen, das DictionaryEntry-Objekt zu ändern, das in der HashTable gespeichert ist. In der Hashtabelle wird nur ein Objekt gespeichert - Ihre Instanz von DictionaryEntry. Das Ändern des Schlüssels oder des Werts reicht aus, um die HashTable zu ändern und den Enumerator ungültig zu machen.
Sie können dies außerhalb der Schleife tun:
Erstellen Sie zunächst eine Liste aller Schlüssel der Werte, die Sie ändern möchten, und durchlaufen Sie stattdessen diese Liste.
quelle
Sie können eine Listenkopie von erstellen
dict.Values
und dann dieList.ForEach
Lambda-Funktion für die Iteration verwenden (oder eineforeach
Schleife, wie zuvor vorgeschlagen).quelle
Zusammen mit den anderen Antworten dachte ich, ich würde beachten, dass Sie, wenn Sie sie erhalten
sortedDictionary.Keys
odersortedDictionary.Values
dannforeach
durchlaufen, sie auch in sortierter Reihenfolge durchlaufen. Dies liegt daran, dass diese MethodenSystem.Collections.Generic.SortedDictionary<TKey,TValue>.KeyCollection
oderSortedDictionary<TKey,TValue>.ValueCollection
Objekte zurückgeben, die die Art des ursprünglichen Wörterbuchs beibehalten.quelle
Diese Antwort dient zum Vergleich zweier Lösungen, nicht als Lösungsvorschlag.
Anstatt eine andere Liste zu erstellen, wie in anderen Antworten vorgeschlagen, können Sie eine
for
Schleife verwenden, die das WörterbuchCount
für die Schleifenstoppbedingung undKeys.ElementAt(i)
zum Abrufen des Schlüssels verwendet.Bei firs dachte ich, das wäre effizienter, weil wir keine Schlüsselliste erstellen müssen. Nach einem Test stellte ich fest, dass die
for
Schleifenlösung viel weniger ist effizient ist. Bei Liste auf meinem PC.Prüfung:
Ergebnisse:
quelle