This article has been localized into Spanish by the community.
Dictionaries / Diccionarios
Los diccionarios en C # implementan la interfaz IDictionary. Existen varios tipos de Diccionario, pero el más utilizado es el Diccionario genérico, a menudo denominado Dictionary<TKey, TValue> : contiene una clave específica de tipo y un valor correspondiente específico de tipo. Esto es básicamente lo que separa un Diccionario de una Lista: los elementos de una lista vienen en un orden específico y se puede acceder a ellos mediante un índice numérico, donde los elementos de un Diccionario se almacenan con una clave única, que luego se puede utilizar para recuperar el Artículo de nuevo.
Investigaremos más sobre los diccionarios, pero primero, veamos un ejemplo simple, para mostrarle de qué se trata:
Dictionary<string, int> users = new Dictionary<string, int>();
users.Add("John Doe", 42);
users.Add("Jane Doe", 38);
users.Add("Joe Doe", 12);
users.Add("Jenna Doe", 12);
Console.WriteLine("John Doe is " + users["John Doe"] + " years old");
Conozca a la familia Doe, que una vez más son los datos de prueba para un ejemplo en este tutorial. Papá, mamá y los gemelos Joe y Jenna. Observe cómo defino el Diccionario para usar una cadena como clave (en este caso, el nombre) y un número entero para el valor (en este caso, una edad). Lo bueno es que esto nos permite acceder a un elemento del diccionario utilizando la clave (nombre), en lugar de un índice numérico. Puede ver eso en acción en la última línea del ejemplo: entre un conjunto de corchetes, simplemente especificamos la clave para acceder al valor (la edad).
Aquí hay dos cosas importantes que debe saber: en primer lugar, la clave debe ser única. En este caso, cuando usamos una cadena como clave, significa que no puede agregar dos usuarios con el mismo nombre. Eso tiene bastante sentido, porque cuando puede usar la clave para hacer referencia a un solo elemento, la clave solo puede apuntar a un valor. Por otro lado, esto hace que este ejemplo sea un poco demasiado simple, porque obviamente no puedes tener una colección de usuarios donde no puedan existir nombres duplicados, pero ten paciencia conmigo por ahora.
La otra cosa que deberá recordar, al acceder a los valores de un diccionario, es que la clave debe existir en la colección, cuando intente acceder a su valor. En otras palabras, mi ejemplo solo era seguro porque tenía el control total de lo que contenía la lista; en la mayoría de las situaciones, siempre debe verificar si la clave existe, antes de intentar usarla, de esta manera:
string key = "John Doe";
if(users.ContainsKey(key))
Console.WriteLine("John Doe is " + users[key] + " years old");
Si intenta agregar una clave que ya existe, o si intenta acceder a un valor con una clave que no existe, .NET generará una excepción. Esto puede sonar obvio, pero ambos se encuentran muy comúnmente en los registros de excepciones de todo el mundo.
Trabajando con los elementos.
Acceder a un solo elemento puede ser muy útil, pero ¿qué sucede si desea recorrer la colección y, por ejemplo, ¿buscar algo? En ese caso, lo primero que debe tener en cuenta es que los elementos de la lista obviamente no son simplemente un objeto simple; en cambio, el Diccionario contiene elementos del tipo KeyValuePair<TKey, TValue>. Las T son los tipos que ha utilizado para declarar la lista, en este caso, una cadena y un número entero. Así que recorrer la colección con un bucle foreach se vería así:
Dictionary<string, int> users = new Dictionary<string, int>()
{
{ "John Doe", 42 },
{ "Jane Doe", 38 },
{ "Joe Doe", 12 },
{ "Jenna Doe", 12 }
};
foreach (KeyValuePair<string, int> user in users)
{
Console.WriteLine(user.Key + " is " + user.Value + " years old");
}
Lo primero que puede notar es que aproveché la oportunidad para cambiar la forma en que inicializamos el diccionario; en lugar de agregar manualmente cada elemento después de crear una instancia del diccionario, usamos la sintaxis del inicializador de colección, como se describe en un artículo anterior.
Quitando eso, ahora tenemos el mismo diccionario que antes, vamos a recorrerlo. Como puede ver, uso un bucle foreach y he declarado el tipo de elemento que espero como KeyValuePair<string, int>: exactamente los mismos dos tipos utilizados para declarar el diccionario. Ahora podemos acceder tanto a la clave como al valor (nombre y edad) para cada elemento, y lo usamos para generar una cadena simple de información sobre la persona en la Consola.
El orden de los elementos.
El ejemplo anterior nos lleva a un punto muy importante: a diferencia de una Lista, donde el orden básico de los elementos está determinado por índices numéricos, el orden de los elementos en un diccionario no es determinista; simplemente no puede confiar en que los elementos estén en cierto orden, ni siquiera cuando agrega manualmente cada elemento individualmente. Claro, cuando ejecuta el ejemplo anterior, es probable que experimente que los elementos están exactamente en el mismo orden en que los agregamos, pero eso no está garantizado, y tan pronto como tenga un diccionario con más elementos y comience a agregar y eliminar elementos, el orden probablemente cambiará.
La clase Dictionary no viene con un método Sort (), porque al final, incluso si lo ordena, el orden podría cambiar tan pronto como comience a trabajar con él nuevamente. En su lugar, puede usar los métodos OrderBy () y OrderByDescending () de LINQ (más sobre eso en otro capítulo) para obtener una copia ordenada del Diccionario. Esto también le permite ordenar por clave o por valor, lo que podría ser útil en nuestro ejemplo, para sacar a los usuarios en el orden de su edad:
Dictionary<string, int> users = new Dictionary<string, int>()
{
{ "John Doe", 42 },
{ "Jane Doe", 38 },
{ "Joe Doe", 12 },
{ "Jenna Doe", 12 }
};
foreach (KeyValuePair<string, int> user in users.OrderBy(user => user.Value))
{
Console.WriteLine(user.Key + " is " + user.Value + " years old");
}
Si ejecuta el ejemplo, verá que aunque el diccionario se declare con los elementos en un orden, podemos sacarlos fácilmente en otro orden, como mejor nos parezca. Solo recuerde que usted es responsable de asegurarse de sacar los elementos en el orden que desee, porque .NET Framework los almacena exactamente como lo considera conveniente.