2009-09-10 18 views

Respuesta

172

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 le permite hacer).

Por ejemplo, se puede tomar una carga de tipos de .NET y construir una búsqueda por el espacio de nombres ... entonces llegar a todos los tipos en un espacio de nombres particular, muy fácilmente:

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); 
     } 
    } 
} 

(me gustaría normalmente . var utilizar para la mayoría de estas declaraciones, en código normal)

+43

Creo que para hacer esta respuesta mejor podrías reemplazar algunos de los vars. Para fines de aprendizaje, creo que es más fácil de seguir, cuando los tipos se expresan claramente. Solo mis 2 centavos :) –

+3

Si tiene lo mejor de ambos mundos, ¿por qué molestarse con un diccionario? –

+12

@KyleBaran: Porque no tendría sentido para colecciones genuinas de pares clave/valor, donde solo hay un valor único por clave. –

11

no he utilizado con éxito antes, pero aquí es mi ir:

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

51

Una forma de pensarlo es esto: 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()); 
     } 
    } 
} 
+2

¿Puede haber cero elementos en un resultado de búsqueda? ¿Cómo lo conseguirías? (La búsqueda es públicamente inmutable por lo que puedo decir, y no creo que ToLookup efectivamente invente las claves.) –

+8

Técnicamente, sí, ya que una búsqueda devuelve una colección vacía para una clave inexistente (edité mi publicación para agregar una muestra de código que muestra esto). – bobbymcr

5

Creo que se puede argumentar de esta manera: suponga que está creando una estructura de datos para almacenar el contenido de un directorio telefónico. 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 se correlacionará con varios valores posibles.

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

+0

Su respuesta inspiró mi pregunta de seguimiento ["¿Cómo ToLookup() con múltiples índices?"] (Http://stackoverflow.com/questions/15734454/how-tolookup-with-multiple-indexes). ¿Cómo puedo reproducir tal, con múltiples índices, búsqueda? ¿Podría responderlo posiblemente usando cualquier otra muestra o referencia donde sea posible usar 'Lookup [" Smith "] [" John "]'? – Fulproof

17

Un uso de Lookup podría revertir un Dictionary.

Supongamos que tiene una agenda telefónica implementada como 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 le importa que dos claves correspondan al mismo valor.

Ahora quiere una forma de averiguar a quién pertenece un número de teléfono determinado. Crea un Lookup, agregando todos los KeyValuePairs desde su Dictionary, pero al revés, con el valor como la clave y la clave como el 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.La construcción de un Dictionary con los mismos datos se reduciría de datos (o no, dependiendo de cómo lo hizo), ya que de

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

significa que la segunda entrada sobrescribe el primero - el Doc ya no está 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"); 

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

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

Cuestiones relacionadas