Diferencia entre Lookup () y Dictionary (Of list ())

Estoy tratando de entender qué estructuras de datos son las más eficientes y cuándo / dónde usar cuáles.

Ahora, podría ser que simplemente no entiendo las estructuras lo suficientemente bien, pero ¿cómo es un ILookup(of key, ...) diferente de un Dictionary(of key, list(of ...)) ?

También, ¿dónde quisiera usar un ILookup y dónde sería más eficiente en términos de velocidad de progtwig / memoria / acceso a datos, etc.?

Dos diferencias significativas:

  • Lookup es inmutable. Yay 🙂 (Al menos, creo que la clase de Lookup concreta es inmutable, y la interfaz ILookup no proporciona ningún miembro mutante. Por supuesto, podría haber otras implementaciones mutables).
  • Cuando busca una clave que no está presente en una búsqueda, obtiene una secuencia vacía en lugar de una KeyNotFoundException . (Por lo tanto, no hay TryGetValue , AFAICR).

Es probable que sean equivalentes en eficiencia: la búsqueda puede usar un Dictionary> detrás de las escenas, por ejemplo. Elija entre ellos en función de sus requisitos. Personalmente, me parece que la búsqueda es generalmente un mejor ajuste que un Dictionary> , principalmente debido a los dos primeros puntos anteriores.

Tenga en cuenta que, como detalle de la implementación, la implementación concreta de IGrouping<,> que se utiliza para los valores implementa IList , lo que significa que es eficiente de usar con Count() , ElementAt() etc.

Es interesante que nadie haya indicado la mayor diferencia real (tomada directamente de MSDN ):

Una búsqueda se asemeja a un diccionario. La diferencia es que un diccionario asigna claves a valores únicos, mientras que una búsqueda mapea claves para colecciones de valores.

Tanto un Dictionary> y una Lookup lógicamente pueden contener datos organizados de manera similar y ambos tienen el mismo orden de eficacia. La principal diferencia es que una Lookup es inmutable: no tiene métodos Add() ni constructor público (y como mencionó Jon, puede consultar una clave inexistente sin una excepción y tener la clave como parte de la agrupación).

En cuanto a cuál usas, realmente depende de cómo quieras usarlos. Si mantiene un mapa de clave para varios valores que se modifican constantemente, entonces un Dictionary> probablemente sea mejor ya que es mutable.

Sin embargo, si tiene una secuencia de datos y solo quiere una vista de solo lectura de los datos organizados por clave, entonces una búsqueda es muy fácil de construir y le dará una instantánea de solo lectura.

La principal diferencia entre un ILookup y un Dictionary> es que un diccionario es mutable; puede agregar o eliminar claves, y también agregar o eliminar elementos de la lista que se busca. Un ILookup es inmutable y no se puede modificar una vez creado.

La implementación subyacente de ambos mecanismos será la misma o similar, por lo que su velocidad de búsqueda y huella de memoria será aproximadamente la misma.

Otra diferencia aún no mencionada es que Lookup () admite claves nulas :

La clase de búsqueda implementa la interfaz ILookup. La búsqueda es muy similar a un diccionario, excepto que se permite mapear múltiples valores a la misma clave, y se admiten claves nulas.

Cuando la excepción no es una opción, vaya a Buscar

Si intenta obtener una estructura tan eficiente como un Dictionary pero no está seguro de que no haya una clave duplicada en la entrada, la Lookup es más segura.

Como se menciona en otra respuesta, también admite claves nulas, y devuelve siempre un resultado válido cuando se consulta con datos arbitrarios, por lo que aparece como más resistente a la entrada desconocida (menos propenso que el diccionario para generar excepciones).

Y es especialmente cierto si lo compara con la función System.Linq.Enumerable.ToDictionary :

 // won't throw new[] { 1, 1 }.ToLookup(x => x); // System.ArgumentException: An item with the same key has already been added. new[] { 1, 1 }.ToDictionary(x => x); 

La alternativa sería escribir su propio código duplicado de administración de claves dentro de un bucle foreach .

Consideraciones de rendimiento, Diccionario: un claro ganador

Si no necesita una lista y va a administrar una gran cantidad de elementos, Dictionary (o incluso su propia estructura personalizada) sería más eficiente:

  Stopwatch stopwatch = new Stopwatch(); var list = new List(); for (int i = 0; i < 5000000; ++i) { list.Add(i.ToString()); } stopwatch.Start(); var lookup = list.ToLookup(x => x); stopwatch.Stop(); Console.WriteLine("Creation: " + stopwatch.Elapsed); // ... Same but for ToDictionary var lookup = list.ToDictionary(x => x); // ... 

Como Lookup tiene que mantener una lista de elementos para cada clave, es más lenta que Dictionary (alrededor de 3 veces más lenta para una gran cantidad de elementos)

Velocidad de búsqueda: Creación: 00: 00: 01.5760444

Velocidad del diccionario: Creación: 00: 00: 00.4418833