Estoy tratando de construir un gráfico circular a partir de un diccionario. Antes de mostrar el gráfico circular, quiero ordenar los datos. Estoy eliminando cualquier rebanada de tarta que sería menos del 5% de la tarta y poniéndola en una rebanada de tarta "Otro". Sin embargo estoy obteniendo unCollection was modified; enumeration operation may not execute
excepción en tiempo de ejecución.
Entiendo por qué no puede agregar o eliminar elementos de un diccionario mientras itera sobre ellos. Sin embargo, no entiendo por qué no puede simplemente cambiar un valor para una clave existente dentro del ciclo foreach.
Cualquier sugerencia con respecto a: arreglar mi código, sería apreciada.
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);
Llame al
ToList()
en elforeach
bucle. De esta manera no necesitamos una copia de la variable temporal. Depende de Linq, que está disponible desde .Net 3.5.fuente
foreach(var pair in colStates.ToList())
para evitar tener acceso a la clave y al valor, lo que evita tener que recurrir acolStates[key]
...Estás modificando la colección en esta línea:
Al hacerlo, esencialmente está eliminando y reinsertando algo en ese punto (en lo que respecta a IEnumerable de todos modos.
Si edita un miembro del valor que está almacenando, estaría bien, pero está editando el valor en sí mismo y a IEnumberable no le gusta eso.
La solución que he usado es eliminar el bucle foreach y simplemente usar un bucle for. Un bucle simple para no verificará los cambios que sabe que no afectarán la colección.
Así es como puedes hacerlo:
fuente
colStates.Keys
en lugar dekeys
.No puede modificar las claves ni los valores directamente en ForEach, pero puede modificar sus miembros. Por ejemplo, esto debería funcionar:
fuente
¿Qué tal simplemente hacer algunas consultas linq contra su diccionario y luego vincular su gráfico a los resultados de esos? ...
fuente
Si te sientes creativo, podrías hacer algo como esto. Recorra el diccionario hacia atrás para realizar sus cambios.
Ciertamente no es idéntico, pero de todos modos puede estar interesado ...
fuente
Debe crear un nuevo diccionario a partir del anterior en lugar de modificarlo en su lugar. Algo parecido (también iterar sobre KeyValuePair <,> en lugar de usar una búsqueda de clave:
fuente
Comenzando con .NET 4.5 Puede hacer esto con ConcurrentDictionary :
Sin embargo, tenga en cuenta que su rendimiento es en realidad mucho peor que un simple
foreach dictionary.Kes.ToArray()
:Resultado:
fuente
No puede modificar la colección, ni siquiera los valores. Puede guardar estos casos y eliminarlos más tarde. Terminaría así:
fuente
Descargo de responsabilidad: no hago mucho C #
Está intentando modificar el objeto DictionaryEntry que está almacenado en HashTable. Hashtable solo almacena un objeto: su instancia de DictionaryEntry. Cambiar la clave o el valor es suficiente para cambiar HashTable y hacer que el enumerador deje de ser válido.
Puedes hacerlo fuera del ciclo:
creando primero una lista de todas las claves de los valores que desea cambiar e iterar a través de esa lista.
fuente
Puede hacer una copia de la lista de
dict.Values
, luego puede usar laList.ForEach
función lambda para la iteración (o unforeach
bucle, como se sugirió anteriormente).fuente
Junto con las otras respuestas, pensé que notaría que si obtienes
sortedDictionary.Keys
osortedDictionary.Values
y luego las repitesforeach
, también lo harás en orden ordenado. Esto se debe a que esos métodos devuelvenSystem.Collections.Generic.SortedDictionary<TKey,TValue>.KeyCollection
uSortedDictionary<TKey,TValue>.ValueCollection
objetos, que mantienen el tipo del diccionario original.fuente
Esta respuesta es para comparar dos soluciones, no una solución sugerida.
En lugar de crear otra lista como sugieren otras respuestas, puede usar un
for
bucle usando el diccionarioCount
para la condición de detención del bucle yKeys.ElementAt(i)
para obtener la clave.Al principio pensé que esto sería más eficiente porque no necesitamos crear una lista de claves. Después de ejecutar una prueba, descubrí que el
for
solución de bucle es mucho menos eficiente. La razón es porqueElementAt
es O (n) en eldictionary.Keys
propiedad, busca desde el comienzo de la colección hasta llegar al enésimo elemento.Prueba:
Resultados:
fuente