J'essaie de créer un graphique à secteurs à partir d'un dictionnaire. Avant d'afficher le graphique à secteurs, je souhaite ranger les données. Je supprime toutes les tranches de tarte qui représenteraient moins de 5% de la tarte et les mets dans une tranche de tarte «Autre». Cependant, je reçois une Collection was modified; enumeration operation may not execute
exception au moment de l'exécution.
Je comprends pourquoi vous ne pouvez pas ajouter ou supprimer des éléments d'un dictionnaire lors de leur itération. Cependant, je ne comprends pas pourquoi vous ne pouvez pas simplement modifier une valeur pour une clé existante dans la boucle foreach.
Toute suggestion concernant la fixation de mon code serait appréciée.
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);
Appelez le
ToList()
dans laforeach
boucle. De cette façon, nous n'avons pas besoin d'une copie de la variable temporaire. Cela dépend de Linq qui est disponible depuis .Net 3.5.la source
foreach(var pair in colStates.ToList())
pour éviter d'avoir accès à la clé et à la valeur ce qui évite d'avoir à appeler encolStates[key]
..Vous modifiez la collection dans cette ligne:
Ce faisant, vous supprimez et réinsérez essentiellement quelque chose à ce stade (en ce qui concerne IEnumerable de toute façon.
Si vous modifiez un membre de la valeur que vous stockez, ce serait OK, mais vous modifiez la valeur elle-même et IEnumberable n'aime pas ça.
La solution que j'ai utilisée est d'éliminer la boucle foreach et d'utiliser simplement une boucle for. Une simple boucle for ne vérifiera pas les modifications dont vous savez qu'elles n'affecteront pas la collection.
Voici comment vous pouvez le faire:
la source
colStates.Keys
à la place dekeys
.Vous ne pouvez pas modifier les clés ni les valeurs directement dans un ForEach, mais vous pouvez modifier leurs membres. Par exemple, cela devrait fonctionner:
la source
Que diriez-vous de faire quelques requêtes linq sur votre dictionnaire, puis de lier votre graphique aux résultats de celles-ci? ...
la source
Si vous vous sentez créatif, vous pouvez faire quelque chose comme ça. Faites une boucle dans le dictionnaire pour effectuer vos modifications.
Certainement pas identique, mais vous pourriez être intéressé quand même ...
la source
Vous devez créer un nouveau dictionnaire à partir de l'ancien plutôt que de le modifier sur place. Quelque chose comme (également itérer sur KeyValuePair <,> plutôt que d'utiliser une recherche de clé:
la source
À partir de .NET 4.5 Vous pouvez le faire avec ConcurrentDictionary :
Notez cependant que ses performances sont en réalité bien pires qu'un simple
foreach dictionary.Kes.ToArray()
:Résultat:
la source
Vous ne pouvez pas modifier la collection, pas même les valeurs. Vous pouvez enregistrer ces cas et les supprimer plus tard. Ça finirait comme ça:
la source
Avertissement: je ne fais pas beaucoup de C #
Vous essayez de modifier l'objet DictionaryEntry qui est stocké dans le HashTable. Le Hashtable ne stocke qu'un seul objet - votre instance de DictionaryEntry. La modification de la clé ou de la valeur suffit à modifier le HashTable et à rendre l'énumérateur invalide.
Vous pouvez le faire en dehors de la boucle:
en créant d'abord une liste de toutes les clés des valeurs que vous souhaitez modifier et en parcourant cette liste à la place.
la source
Vous pouvez faire une copie de liste de
dict.Values
, puis vous pouvez utiliser laList.ForEach
fonction lambda pour l'itération, (ou uneforeach
boucle, comme suggéré précédemment).la source
En plus des autres réponses, j'ai pensé que je noterais que si vous obtenez
sortedDictionary.Keys
ousortedDictionary.Values
et queforeach
vous les parcourez ensuite, vous les parcourez également dans un ordre trié. En effet, ces méthodes renvoient des objetsSystem.Collections.Generic.SortedDictionary<TKey,TValue>.KeyCollection
ouSortedDictionary<TKey,TValue>.ValueCollection
qui conservent le type du dictionnaire d'origine.la source
Cette réponse est pour comparer deux solutions, pas une solution suggérée.
Au lieu de créer une autre liste comme d'autres réponses le suggèrent, vous pouvez utiliser une
for
boucle en utilisant le dictionnaireCount
pour la condition d'arrêt de boucle etKeys.ElementAt(i)
pour obtenir la clé.Au début, j'ai pensé que ce serait plus efficace car nous n'avons pas besoin de créer une liste de clés. Après avoir exécuté un test, j'ai trouvé que la
for
solution de boucle est beaucoup moins efficace. La raison en est queElementAt
O (n) sur ledictionary.Keys
propriété, il recherche depuis le début de la collection jusqu'à ce qu'il atteigne le nième élément.Tester:
Résultats:
la source