2009-07-22 10 views
25

¿Cuál es la mejor manera de establecer todos los valores en un diccionario de C#?¿Cuál es la mejor manera de establecer todos los valores en un diccionario de C# <string,bool>?

Esto es lo que estoy haciendo ahora, pero estoy seguro de que hay una manera mejor/más limpia de hacer esto:

Dictionary<string,bool> dict = GetDictionary(); 
var keys = dict.Keys.ToList(); 
for (int i = 0; i < keys.Count; i++) 
{ 
    dict[keys[i]] = false; 
} 

He intentado algunas otras maneras con foreach, pero tenía errores.

+0

Otra pregunta de mis días nuevos :) –

Respuesta

60

Eso es un enfoque razonable, aunque yo preferiría:

foreach (var key in dict.Keys.ToList()) 
{ 
    dict[key] = false; 
} 

La llamada a ToList() hace este trabajo, ya que está sacando y (temporalmente) el ahorro de la lista de claves, por lo que los trabajos de iteración.

+1

Mirando mi código original, no sé por qué no probé esto. –

+2

dict.Keys.Para cada uno (k => dict [k] = falso); – obenda

+0

@obenda [ForEach considered harmfil] (https://blogs.msdn.microsoft.com/ericlippert/2009/05/18/foreach-vs-foreach/). –

-2

Se podía sacar la ToList() y repetir directamente sobre los elementos del diccionario

Dictionary<string, bool> dict = GetDictionary(); 
foreach (var pair in dict) 
{ 
    dict[pair.Key] = false; 
} 
+3

Al cambiar el diccionario se invalida el enumerador, y al seguir usándolo se generará una 'InvalidOperationException'. –

-4

hacerlo de la manera que lo tienes en este momento ... foreach es lento. foreach puede estar más limpio, pero se usa demasiado para golpear el rendimiento.

Editar:
http://www.codeproject.com/KB/cs/foreach.aspx
http://www.madprops.org/blog/for-vs-foreach-performance/

+1

¿Cómo es 'foreach' lento? –

+0

Ver arriba. Perdón por no proporcionar evidencia en la publicación original. – Polaris878

+0

El método 'foreach' que figura en la primera publicación * es * lento ... para manipular los depósitos internos existentes del diccionario. –

5

Si no está utilizando Bools de tres estados, entonces usted puede utilizar HashSet<string>, y llamar a Clear() para establecer los valores de "falsas".

+0

Esta es una buena alternativa –

+0

No estoy usando tri-state bools, pero no entiendo cómo implementar lo que está hablando. ¡Se ve bien, sin embargo! –

+1

@Billy: si la cadena está en 'HashSet', entonces es verdad. Si no está en el 'HashSet', es falso. Use Agregar/Eliminar en lugar de establecer verdadero/falso. Esto será * muy * rápido, pero no hay forma de representar un tercer estado "perdido". –

2

Hice un perfil de la diferencia entre las soluciones de Billy y Reed. Polaris878, toma buena nota de los resultados y recuerda que la optimización prematura es la raíz de todo mal ;-)

Reescribí las soluciones en VB (porque actualmente estoy programando en ese idioma) y usé claves int (por simplicidad), de lo contrario, es exactamente el mismo código. Ejecuté el código con un diccionario de 10 millones de entradas con un valor de "verdadero" para cada entrada. solución original

Billy bruja del médico:

Dim keys = dict.Keys.ToList 
For i = 0 To keys.Count - 1 
    dict(keys(i)) = False 
Next 

milisegundos transcurridos: 415

solución de

Reed Copsey:

For Each key In dict.Keys.ToList 
    dict(key) = False 
Next 

milisegundos transcurridos: 395

Así que en ese caso el foreach es en realidad más rápido.

18

Una solución de una sola línea:

dict = dict.ToDictionary(p => p.Key, p => false); 
3

No estoy seguro de si es la mejor manera pero yo estaba buscando algo en una sola línea y esto funcionó para mí

mydict.Keys.ToList().ForEach(k => mydict[k] = false); 
Cuestiones relacionadas