c# recorrer ¿Cuál es la mejor manera de iterar sobre un diccionario?




search in dictionary c# (20)

foreach(KeyValuePair<string, string> entry in myDictionary)
{
    // do something with entry.Value or entry.Key
}

He visto algunas formas diferentes de iterar sobre un diccionario en C #. ¿Hay una forma estándar?


Encontré este método en la documentación de la clase DictionaryBase en MSDN:

foreach (DictionaryEntry de in myDictionary)
{
     //Do some stuff with de.Value or de.Key
}

Este fue el único que pude obtener funcionando correctamente en una clase que heredó de DictionaryBase.


A partir de C # 7, puede deconstruir objetos en variables. Creo que esta es la mejor manera de iterar sobre un diccionario.

Ejemplo:

Cree un método de extensión en KeyValuePair<TKey, TVal> que lo KeyValuePair<TKey, TVal> :

public static void Deconstruct<TKey, TVal>(this KeyValuePair<TKey, TVal> pair, out TKey, out TVal val)
{
   key = pair.Key;
   val = pair.Value;
}

Iterar sobre cualquier Dictionary<TKey, TVal> de la siguiente manera

// Dictionary can be of any types, just using 'int' and 'string' as examples.
Dictionary<int, string> dict = new Dictionary<int, string>();

// Deconstructor gets called here.
foreach (var (key, value) in dict)
{
   Console.WriteLine($"{key} : {value}");
}

La forma más simple de iterar un diccionario:

foreach(var item in myDictionary)
{ 
    Console.WriteLine(item.Key);
    Console.WriteLine(item.Value);
}

además de los puestos de mayor rango donde hay una discusión entre el uso

foreach(KeyValuePair<string, string> entry in myDictionary)
{
    // do something with entry.Value or entry.Key
}

o

foreach(var entry in myDictionary)
{
    // do something with entry.Value or entry.Key
}

el más completo es el siguiente porque puede ver el tipo de diccionario desde la inicialización, kvp es KeyValuePair

var myDictionary = new Dictionary<string, string>(x);//fill dictionary with x

foreach(var kvp in myDictionary)//iterate over dictionary
{
    // do something with kvp.Value or kvp.Key
}

Si está intentando usar un Diccionario genérico en C #, como si usara una matriz asociativa en otro idioma:

foreach(var item in myDictionary)
{
  foo(item.Key);
  bar(item.Value);
}

O, si solo necesita iterar sobre la colección de claves, use

foreach(var item in myDictionary.Keys)
{
  foo(item);
}

Y por último, si solo te interesan los valores:

foreach(var item in myDictionary.Values)
{
  foo(item);
}

(Tenga en cuenta que la palabra clave var es una característica opcional de C # 3.0 y superior, también puede usar el tipo exacto de sus claves / valores aquí)


También puede probar esto en diccionarios grandes para procesamiento multiproceso.

dictionary
.AsParallel()
.ForAll(pair => 
{ 
    // Process pair.Key and pair.Value here
});

En general, pedir "la mejor manera" sin un contexto específico es como preguntar cuál es el mejor color.

Por un lado, hay muchos colores y no hay mejor color. Depende de la necesidad y, a menudo, del gusto.

Por otro lado, hay muchas maneras de iterar sobre un Diccionario en C # y no hay una mejor manera. Depende de la necesidad y, a menudo, del gusto.

Manera más sencilla

foreach (var kvp in items)
{
    // key is kvp.Key
    doStuff(kvp.Value)
}

Si solo necesita el valor (permite llamarlo item , más legible que kvp.Value ).

foreach (var item in items.Values)
{
    doStuff(item)
}

Si necesita un orden específico

En general, los principiantes se sorprenden por el orden de enumeración de un Diccionario.

LINQ proporciona una sintaxis concisa que permite especificar el orden (y muchas otras cosas), por ejemplo:

foreach (var kvp in items.OrderBy(kvp => kvp.Key))
{
    // key is kvp.Key
    doStuff(kvp.Value)
}

Una vez más, es posible que sólo necesite el valor. LINQ también proporciona una solución concisa para:

  • iterar directamente en el valor (permite llamarlo item , más legible que kvp.Value )
  • pero ordenados por las llaves

Aquí está:

foreach (var item in items.OrderBy(kvp => kvp.Key).Select(kvp => kvp.Value))
{
    doStuff(item)
}

Hay muchos más casos de uso del mundo real que puede hacer a partir de estos ejemplos. Si no necesita una orden específica, simplemente siga la "manera más directa" (ver arriba).


Escribí una extensión para recorrer un diccionario.

public static class DictionaryExtension
{
    public static void ForEach<T1, T2>(this Dictionary<T1, T2> dictionary, Action<T1, T2> action) {
        foreach(KeyValuePair<T1, T2> keyValue in dictionary) {
            action(keyValue.Key, keyValue.Value);
        }
    }
}

Entonces puedes llamar

myDictionary.ForEach((x,y) => Console.WriteLine(x + " - " + y));

Usted sugirió a continuación para iterar

Dictionary<string,object> myDictionary = new Dictionary<string,object>();
//Populate your dictionary here

foreach (KeyValuePair<string,object> kvp in myDictionary) {
    //Do some interesting things;
}

Para su información, foreach no funciona si el valor es de tipo objeto.


Usando C # 7 , agregue este método de extensión a cualquier proyecto de su solución:

public static class IDictionaryExtensions
{
    public static IEnumerable<(TKey, TValue)> Tuples<TKey, TValue>(
        this IDictionary<TKey, TValue> dict)
    {
        foreach (KeyValuePair<TKey, TValue> kvp in dict)
            yield return (kvp.Key, kvp.Value);
    }
}


Y usa esta sintaxis simple

foreach (var(id, value) in dict.Tuples())
{
    // your code using 'id' and 'value'
}


O éste, si lo prefieres.

foreach ((string id, object value) in dict.Tuples())
{
    // your code using 'id' and 'value'
}


En lugar de lo tradicional.

foreach (KeyValuePair<string, object> kvp in dict)
{
    string id = kvp.Key;
    object value = kvp.Value;

    // your code using 'id' and 'value'
}


El método de extensión transforma el KeyValuePair de su IDictionary<TKey, TValue> en una tuple fuertemente IDictionary<TKey, TValue> , lo que le permite utilizar esta nueva sintaxis cómoda.

Convierte, simplemente, las entradas requeridas del diccionario en tuples , por lo que NO convierte todo el diccionario en tuples , por lo que no hay problemas de rendimiento relacionados con eso.

Hay un solo costo menor que llama al método de extensión para crear una tuple en comparación con el uso de KeyValuePair directamente, lo que NO debería ser un problema si está asignando la Key y el Value propiedades de KeyValuePair a nuevas variables de bucle.

En la práctica, esta nueva sintaxis se adapta muy bien para la mayoría de los casos, excepto en los escenarios de rendimiento ultraalto de bajo nivel, donde aún tiene la opción de simplemente no usarla en ese lugar específico.

Mira esto: MSDN Blog - Nuevas características en C # 7


var dictionary = new Dictionary<string, int>
{
    { "Key", 12 }
};

var aggregateObjectCollection = dictionary.Select(
    entry => new AggregateObject(entry.Key, entry.Value));

Dictionary <TKey, TValue> Es una clase de colección genérica en c # y almacena los datos en el formato del valor clave. La clave debe ser única y no puede ser nula, mientras que el valor puede ser duplicado y nulo. Como cada elemento del diccionario es tratado como KeyValuePair <TKey, TValue> estructura que representa una clave y su valor. y por lo tanto deberíamos tomar el tipo de elemento KeyValuePair <TKey, TValue> durante la iteración del elemento. A continuación se muestra el ejemplo.

Dictionary<int, string> dict = new Dictionary<int, string>();
dict.Add(1,"One");
dict.Add(2,"Two");
dict.Add(3,"Three");

foreach (KeyValuePair<int, string> item in dict)
{
    Console.WriteLine("Key: {0}, Value: {1}", item.Key, item.Value);
}

Los diccionarios son listas especiales, mientras que cada valor en la lista tiene una clave que también es una variable. Un buen ejemplo de un diccionario es una guía telefónica.

   Dictionary<string, long> phonebook = new Dictionary<string, long>();
    phonebook.Add("Alex", 4154346543);
    phonebook["Jessica"] = 4159484588;

Tenga en cuenta que al definir un diccionario, debemos proporcionar una definición genérica con dos tipos: el tipo de clave y el tipo de valor. En este caso, la clave es una cadena, mientras que el valor es un número entero.

También hay dos formas de agregar un solo valor al diccionario, ya sea usando el operador de corchetes o usando el método Agregar.

Para verificar si un diccionario tiene cierta clave, podemos usar el método ContainsKey:

Dictionary<string, long> phonebook = new Dictionary<string, long>();
phonebook.Add("Alex", 415434543);
phonebook["Jessica"] = 415984588;

if (phonebook.ContainsKey("Alex"))
{
    Console.WriteLine("Alex's number is " + phonebook["Alex"]);
}

Para eliminar un elemento de un diccionario, podemos utilizar el método Eliminar. Eliminar un elemento de un diccionario por su clave es rápido y muy eficiente. Al eliminar un elemento de una Lista utilizando su valor, el proceso es lento e ineficiente, a diferencia de la función Eliminar del diccionario.

Dictionary<string, long> phonebook = new Dictionary<string, long>();
phonebook.Add("Alex", 415434543);
phonebook["Jessica"] = 415984588;

phonebook.Remove("Jessica");
Console.WriteLine(phonebook.Count);

Yo diría que foreach es la forma estándar, aunque obviamente depende de lo que estés buscando

foreach(var kvp in my_dictionary) {
  ...
}

¿Es eso lo que estás buscando?



Con .NET Framework 4.7 se puede usar la descomposición

var fruits = new Dictionary<string, int>();
...
foreach (var (fruit, number) in fruits)
{
    Console.WriteLine(fruit + ": " + number);
}

Para hacer que este código funcione en versiones de C # más bajas, agregue el System.ValueTuple NuGet package y escriba en algún lugar

public static class MyExtensions
{
    public static void Deconstruct<T1, T2>(this KeyValuePair<T1, T2> tuple,
        out T1 key, out T2 value)
    {
        key = tuple.Key;
        value = tuple.Value;
    }
}

Hay un montón de opciones. Mi favorito personal es por KeyValuePair

Dictionary<string, object> myDictionary = new Dictionary<string, object>();
// Populate your dictionary here

foreach (KeyValuePair<string,object> kvp in myDictionary)
{
     // Do some interesting things
}

También puedes utilizar las colecciones de claves y valores.


Depende de si buscas las claves o los valores ...

Desde el Dictionary(TKey, TValue) MSDN Dictionary(TKey, TValue) Descripción de la clase:

// When you use foreach to enumerate dictionary elements,
// the elements are retrieved as KeyValuePair objects.
Console.WriteLine();
foreach( KeyValuePair<string, string> kvp in openWith )
{
    Console.WriteLine("Key = {0}, Value = {1}", 
        kvp.Key, kvp.Value);
}

// To get the values alone, use the Values property.
Dictionary<string, string>.ValueCollection valueColl =
    openWith.Values;

// The elements of the ValueCollection are strongly typed
// with the type that was specified for dictionary values.
Console.WriteLine();
foreach( string s in valueColl )
{
    Console.WriteLine("Value = {0}", s);
}

// To get the keys alone, use the Keys property.
Dictionary<string, string>.KeyCollection keyColl =
    openWith.Keys;

// The elements of the KeyCollection are strongly typed
// with the type that was specified for dictionary keys.
Console.WriteLine();
foreach( string s in keyColl )
{
    Console.WriteLine("Key = {0}", s);
}

Por ejemplo, si desea iterar sobre la colección de valores de forma predeterminada, creo que puede implementar IEnumerable <>, donde T es el tipo de objeto de valores en el diccionario, y "este" es un Diccionario.

public new IEnumerator<T> GetEnumerator()
{
   return this.Values.GetEnumerator();
}




loops