Próbuję zbudować wykres kołowy ze słownika. Przed wyświetleniem wykresu kołowego chcę uporządkować dane. Usuwam wszystkie plasterki ciasta, które byłyby mniejsze niż 5% ciasta i umieszczam je w „innym” kawałku ciasta. Jednak dostaję Collection was modified; enumeration operation may not execute
wyjątek w czasie wykonywania.
Rozumiem, dlaczego nie można dodawać ani usuwać elementów ze słownika podczas iteracji nad nimi. Nie rozumiem jednak, dlaczego nie można po prostu zmienić wartości istniejącego klucza w pętli foreach.
Będziemy wdzięczni za wszelkie sugestie dotyczące: naprawy mojego kodu.
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);
Zadzwoń
ToList()
wforeach
pętli. W ten sposób nie potrzebujemy kopii zmiennej temp. To zależy od Linq, który jest dostępny od wersji .Net 3.5.źródło
foreach(var pair in colStates.ToList())
aby uniknąć dostępu do Klucza i Wartości, co pozwala uniknąć konieczności wywoływaniacolStates[key]
..Modyfikujesz kolekcję w tym wierszu:
Robiąc to, zasadniczo usuwasz i ponownie wstawiasz coś w tym momencie (jeśli chodzi o IEnumerable i tak.
Jeśli edytujesz członka przechowywanej wartości, byłoby to w porządku, ale edytujesz samą wartość, a IEnumberable tego nie lubi.
Rozwiązaniem, które zastosowałem, jest wyeliminowanie pętli foreach i użycie pętli for. Prosta pętla for nie sprawdza zmian, o których wiesz, że nie wpłyną na kolekcję.
Oto jak możesz to zrobić:
źródło
colStates.Keys
zamiastkeys
.Nie możesz modyfikować kluczy ani wartości bezpośrednio w ForEach, ale możesz modyfikować ich członków. Np. Powinno to działać:
źródło
Co powiesz na wykonanie kilku zapytań linq na słownik, a następnie powiązanie wykresu z ich wynikami? ...
źródło
Jeśli czujesz się kreatywny, możesz zrobić coś takiego. Pętlę do tyłu w słowniku, aby wprowadzić zmiany.
Na pewno nie identyczne, ale i tak możesz być zainteresowany ...
źródło
Musisz utworzyć nowy Słownik ze starego, a nie modyfikować w miejscu. Coś w rodzaju (iteruj również nad KeyValuePair <,> zamiast wyszukiwania klucza:
źródło
Począwszy od .NET 4.5 Możesz to zrobić za pomocą ConcurrentDictionary :
Zauważ jednak, że jego wydajność jest znacznie gorsza niż prosta
foreach dictionary.Kes.ToArray()
:Wynik:
źródło
Nie możesz modyfikować kolekcji, nawet wartości. Możesz zapisać te skrzynki i usunąć je później. Skończy się tak:
źródło
Oświadczenie: nie robię dużo C #
Próbujesz zmodyfikować obiekt DictionaryEntry, który jest przechowywany w HashTable. Hashtable przechowuje tylko jeden obiekt - twoją instancję DictionaryEntry. Zmiana klucza lub wartości wystarczy, aby zmienić tabelę mieszania i spowodować, że moduł wyliczający stanie się nieprawidłowy.
Możesz to zrobić poza pętlą:
najpierw tworząc listę wszystkich kluczy wartości, które chcesz zmienić, i zamiast tego powtarzaj tę listę.
źródło
Możesz wykonać kopię listy
dict.Values
, a następnie możesz użyćList.ForEach
funkcji lambda do iteracji (lubforeach
pętli, jak sugerowano wcześniej).źródło
Wraz z innymi odpowiedziami, pomyślałem, że pamiętać, że jeśli masz
sortedDictionary.Keys
lubsortedDictionary.Values
a następnie pętli nad nimiforeach
, można również przejść posortowanych. Jest tak, ponieważ metody te zwracająSystem.Collections.Generic.SortedDictionary<TKey,TValue>.KeyCollection
lubSortedDictionary<TKey,TValue>.ValueCollection
obiekty, które zachowują rodzaj oryginalnego słownika.źródło
Ta odpowiedź służy do porównania dwóch rozwiązań, a nie sugerowanego rozwiązania.
Zamiast tworzyć kolejną listę, jak sugerują inne odpowiedzi, można użyć
for
pętli za pomocą słownikaCount
dla warunku zatrzymania pętli iKeys.ElementAt(i)
uzyskania klucza.W firs myślałem, że będzie to bardziej wydajne, ponieważ nie musimy tworzyć listy kluczy. Po uruchomieniu testu stwierdziłem, że
for
rozwiązanie pętli jest znacznie mniej wydajne. Powodem jest to, żeElementAt
jest O (n) nadictionary.Keys
właściwości , szuka ona od początku kolekcji, aż dojdzie do n-tego elementu.Test:
Wyniki:
źródło