2009-03-24 28 views
21

¿Cómo enumero un diccionario?Enumeración del diccionario en C#

Supongamos que uso foreach() para la enumeración dictionay. No puedo actualizar un par de clave/valor dentro de foreach(). Entonces quiero otro método.

Respuesta

75

Enumerar un diccionario que sea enumerar los valores dentro de ella:

Dictionary<int, string> dic; 

foreach(string s in dic.Values) 
{ 
    Console.WriteLine(s); 
} 

o los KeyValuePairs

foreach(KeyValuePair<int, string> kvp in dic) 
{ 
    Console.WriteLine("Key : " + kvp.Key.ToString() + ", Value : " + kvp.Value); 
} 

o las teclas

foreach(int key in dic.Keys) 
{ 
    Console.WriteLine(key.ToString()); 
} 

Si desea actualizar los elementos dentro del diccionario debe hacerlo de forma ligeramente diferente, porque no puede actualizar la instancia mientras enumera. Lo que usted tiene que hacer es enumerar una colección diferente que no está siendo actualizado, así:

Dictionary<int, string> newValues = new Dictionary<int, string>() { 1, "Test" }; 
foreach(KeyValuePair<int, string> kvp in newValues) 
{ 
    dic[kvp.Key] = kvp.Value; // will automatically add the item if it's not there 
} 

Para eliminar elementos, hacerlo de una manera similar, la enumeración de la colección de elementos que desea eliminar en vez que el diccionario en sí.

List<int> keys = new List<int>() { 1, 3 }; 
foreach(int key in keys) 
{ 
    dic.Remove(key); 
} 
+0

O puede enumerar las claves. – strager

+0

¡De hecho! Gracias por señalar eso. – Ian

+2

Supongo que enumerar las claves sería más común que enumerar solo los valores (al menos según mi experiencia), ya que puede encontrar el valor de la clave con bastante facilidad (ese es el punto del diccionario). – Wedge

8

Foreach. Hay tres formas: Puede enumerar sobre la propiedad Keys, sobre la propiedad Values o sobre el diccionario mismo, que es un enumerador de KeyValuePair<TKey, TValue>.

9

En respuesta al problema "No puedo actualizar el valor/clave dentro de foreach()", no puede modificar una colección al enumerarla. Me gustaría abordar este haciendo una copia de la colección Claves:

Dictionary<int,int> dic=new Dictionary<int, int>(); 

//...fill the dictionary 

int[] keys = dic.Keys.ToArray(); 
foreach (int i in keys) 
{ 
    dic.Remove(i); 
} 
+0

No es necesario .ToArray() AFAIK. . Keys devuelve un IEnumerable. – strager

+1

seguro, pero si el diccionario se altera en el ciclo, ¿qué ocurre con esa enumeración? cambia, seguramente? – spender

+0

No lo hubiera pensado así. El dic.Keys devolverá un IEnumerable en este caso, que serán todos los valores. Si tuviera que usar el IEnumerator en su lugar, podría ser el caso. – Ian

2

Me acaba de responder la misma pregunta (actualizado) para las listas, así que aquí es lo mismo para los diccionarios.

public static void MutateEach(this IDictionary<TKey, TValue> dict, Func<TKey, TValue, KeyValuePair<TKey, TValue>> mutator) 
{ 
    var removals = new List<TKey>(); 
    var additions = new List<KeyValuePair<TKey, TValue>>(); 

    foreach (var pair in dict) 
    { 
     var newPair = mutator(pair.Key, pair.Value); 
     if ((newPair.Key != pair.Key) || (newPair.Value != pair.Value)) 
     { 
      removals.Add(pair.Key); 
      additions.Add(newPair); 
     } 
    } 

    foreach (var removal in removals) 
     dict.Remove(removal); 

    foreach (var addition in additions) 
     dict.Add(addition.Key, addition.Value); 
} 

Tenga en cuenta que tenemos que hacer los cambios fuera del bucle, por lo que no están modificando el diccionario como enumeramos ella. También esto detecta los choques causados ​​por hacer que dos llaves sean iguales: arrojará (debido al uso de Add).

Ejemplo - realizar todas las minúsculas a recortar todos los valores, con un Dictionary<string, string>:

myDict.MutateEach(key => key.ToLower(), value => value.Trim()); 

Si las claves no son únicos cuando se hace minúsculas, esto va a lanzar.