c# .net linq lookup

c# - ¿Cuál es el punto de Lookup<TKey, TElement>?



.net linq (5)

MSDN explica la búsqueda de esta manera:

Una Lookup<TKey, TElement> asemeja a un Dictionary<TKey, TValue> . La diferencia es que un Diccionario <TKey, TValue> asigna claves a valores únicos, mientras que un Lookup <TKey, TElement> asigna claves a colecciones de valores.

No encuentro esa explicación particularmente útil. ¿Para qué se usa Lookup?


Es un cruce entre un IGrouping y un diccionario. Le permite agrupar elementos mediante una clave, pero luego acceder a ellos a través de esa clave de una manera eficiente (en lugar de simplemente iterar sobre todos ellos, que es lo que GroupBy permite hacer).

Por ejemplo, puede tomar una carga de tipos de .NET y crear una búsqueda por espacio de nombres ... luego puede acceder a todos los tipos en un espacio de nombres en particular con mucha facilidad:

using System; using System.Collections.Generic; using System.Linq; using System.Xml; public class Test { static void Main() { // Just types covering some different assemblies Type[] sampleTypes = new[] { typeof(List<>), typeof(string), typeof(Enumerable), typeof(XmlReader) }; // All the types in those assemblies IEnumerable<Type> allTypes = sampleTypes.Select(t => t.Assembly) .SelectMany(a => a.GetTypes()); // Grouped by namespace, but indexable ILookup<string, Type> lookup = allTypes.ToLookup(t => t.Namespace); foreach (Type type in lookup["System"]) { Console.WriteLine("{0}: {1}", type.FullName, type.Assembly.GetName().Name); } } }

(Normalmente usaría var para la mayoría de estas declaraciones, en código normal).


No lo he usado con éxito antes, pero aquí está mi ir:

Un Lookup<TKey, TElement> se comportaría más o menos como un índice de base de datos (relacional) en una tabla sin una restricción única. Úselo en los mismos lugares donde usaría el otro.


Supongo que podría argumentarlo de esta manera: imagine que está creando una estructura de datos para contener el contenido de una guía telefónica. Desea teclear por lastName y luego por firstName. Usar un diccionario aquí sería peligroso porque muchas personas pueden tener el mismo nombre. Entonces, un diccionario siempre, como máximo, asignará un único valor.

Una búsqueda mapeará a potencialmente varios valores.

La búsqueda ["Smith"] ["John"] será una colección de tamaño mil millones.


Un uso de Lookup podría ser revertir un Dictionary .

Supongamos que tiene un directorio telefónico implementado como un Dictionary con un grupo de nombres (únicos) como claves, cada nombre asociado con un número de teléfono. Pero dos personas con diferentes nombres pueden compartir el mismo número de teléfono. Esto no es un problema para un Dictionary , que no se preocupa de que dos claves correspondan al mismo valor.

Ahora desea una forma de averiguar a quién pertenece un número de teléfono determinado. KeyValuePairs una Lookup , agregando todos los KeyValuePairs de su Dictionary , pero al revés, con el valor como clave y la clave como valor. Ahora puede consultar un número de teléfono y obtener una lista de nombres de todas las personas cuyo número de teléfono es. Construir un Dictionary con los mismos datos sería eliminar los datos (o fallar, dependiendo de cómo lo hizo), ya que

dictionary["555-6593"] = "Dr. Emmett Brown"; dictionary["555-6593"] = "Marty McFly";

significa que la segunda entrada sobrescribe la primera: el Doc ya no aparece en la lista.

Tratando de escribir los mismos datos de una manera ligeramente diferente:

dictionary.Add("555-6593", "Dr. Emmett Brown"); dictionary.Add("555-6593", "Marty McFly");

arrojaría una excepción en la segunda línea ya que no puede Add una clave que ya está en el Dictionary .

[Por supuesto, es posible que desee utilizar alguna otra estructura de datos única para realizar búsquedas en ambas direcciones, etc. Este ejemplo significa que debe regenerar la Lookup del Dictionary cada vez que cambie la última. Pero para algunos datos podría ser la solución correcta.]


Una forma de pensarlo es esta: Lookup<TKey, TElement> es similar a Dictionary<TKey, Collection<TElement>> . Básicamente, se puede devolver una lista de cero o más elementos a través de la misma clave.

namespace LookupSample { using System; using System.Collections.Generic; using System.Linq; class Program { static void Main(string[] args) { List<string> names = new List<string>(); names.Add("Smith"); names.Add("Stevenson"); names.Add("Jones"); ILookup<char, string> namesByInitial = names.ToLookup((n) => n[0]); // count the names Console.WriteLine("J''s: {0}", namesByInitial[''J''].Count()); Console.WriteLine("S''s: {0}", namesByInitial[''S''].Count()); Console.WriteLine("Z''s: {0}", namesByInitial[''Z''].Count()); } } }