Я пытаюсь построить круговую диаграмму из словаря. Прежде чем отобразить круговую диаграмму, я хочу привести в порядок данные. Я удаляю любые кусочки пирога, которые будут составлять менее 5% от пирога, и помещаю их в «другой» кусок пирога. Однако я получаю Collection was modified; enumeration operation may not execute
исключение во время выполнения.
Я понимаю, почему вы не можете добавлять или удалять элементы из словаря, просматривая их. Однако я не понимаю, почему вы не можете просто изменить значение для существующего ключа в цикле foreach.
Любые предложения по исправлению моего кода, будут оценены.
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);
Позвоните
ToList()
вforeach
петле. Таким образом, нам не нужно копировать временную переменную. Это зависит от Linq, который доступен с .Net 3.5.источник
foreach(var pair in colStates.ToList())
чтобы избежать доступа к ключу и значению, которое не требует вызоваcolStates[key]
..Вы изменяете коллекцию в этой строке:
Таким образом, вы по существу удаляете и повторно вставляете что-то в этот момент (в любом случае, что касается IEnumerable).
Если вы редактируете участника значения, которое вы храните, это будет нормально, но вы редактируете само значение, а IEnumberable это не нравится.
Решение, которое я использовал, состоит в том, чтобы исключить цикл foreach и просто использовать цикл for. Простой цикл for не проверяет изменения, которые, как вы знаете, не влияют на коллекцию.
Вот как вы можете это сделать:
источник
colStates.Keys
вместоkeys
.Вы не можете изменять ключи или значения непосредственно в ForEach, но вы можете изменять их члены. Например, это должно работать:
источник
Как насчет того, чтобы просто выполнить несколько запросов linq к вашему словарю, а затем связать ваш график с результатами этих? ...
источник
Если вы чувствуете себя творчески, вы можете сделать что-то вроде этого. Перейдите назад по словарю, чтобы внести изменения.
Конечно, не идентичны, но вы можете быть заинтересованы в любом случае ...
источник
Вам нужно создать новый словарь из старого, а не модифицировать на месте. Что-то вроде (также перебираем KeyValuePair <,> вместо использования поиска ключа:
источник
Начиная с .NET 4.5 Вы можете сделать это с ConcurrentDictionary :
Однако обратите внимание, что его производительность на самом деле намного хуже, чем у простого
foreach dictionary.Kes.ToArray()
:Результат:
источник
Вы не можете изменить коллекцию, даже значения. Вы можете сохранить эти случаи и удалить их позже. Это закончилось бы так:
источник
Отказ от ответственности: я не делаю много C #
Вы пытаетесь изменить объект DictionaryEntry, который хранится в HashTable. В Hashtable хранится только один объект - ваш экземпляр DictionaryEntry. Изменение ключа или значения достаточно, чтобы изменить HashTable и сделать перечислитель недействительным.
Вы можете сделать это вне цикла:
сначала создав список всех ключей значений, которые вы хотите изменить, и переберите этот список.
источник
Вы можете сделать копию списка
dict.Values
, затем вы можете использоватьList.ForEach
лямбда-функцию для итерации (илиforeach
цикл, как предлагалось ранее).источник
Наряду с другими ответами, я подумал, что заметил бы, что если вы получите
sortedDictionary.Keys
илиsortedDictionary.Values
затем переберите ихforeach
, вы также пройдете в отсортированном порядке. Это потому, что эти методы возвращаютSystem.Collections.Generic.SortedDictionary<TKey,TValue>.KeyCollection
илиSortedDictionary<TKey,TValue>.ValueCollection
объекты, которые поддерживают вид исходного словаря.источник
Этот ответ предназначен для сравнения двух решений, а не предлагаемого решения.
Вместо того, чтобы создавать другой список, как предлагают другие ответы, вы можете использовать
for
цикл, используя словарьCount
для условия остановки цикла иKeys.ElementAt(i)
для получения ключа.Во-первых, я думал, что это будет более эффективно, потому что нам не нужно создавать список ключей. После запуска теста я обнаружил, что
for
решение по циклу намного менее эффективно. Причина в том, чтоElementAt
O (n) дляdictionary.Keys
свойства, он ищет с начала коллекции, пока не дойдет до n-го элемента.Тест:
Полученные результаты:
источник