Qual è il punto di ricerca <TKey, TElement>?


155

MSDN spiega Lookup in questo modo:

A è Lookup<TKey, TElement> simile a Dictionary<TKey, TValue>. La differenza è che un dizionario <TKey, TValue> mappa le chiavi su valori singoli, mentre una ricerca <TKey, TElement> mappa le chiavi su raccolte di valori.

Non trovo questa spiegazione particolarmente utile. A cosa serve la ricerca?

Risposte:


215

È un incrocio tra an IGroupinge un dizionario. Ti consente di raggruppare gli elementi in base a una chiave, ma poi di accedervi tramite quella chiave in modo efficiente (piuttosto che semplicemente iterandoli su tutti, cosa GroupByche ti consente di fare).

Ad esempio, potresti prendere un carico di tipi .NET e creare una ricerca per spazio dei nomi ... quindi arrivare a tutti i tipi in uno spazio dei nomi molto facilmente:

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 userei varper la maggior parte di queste dichiarazioni, in codice normale.)


59
Penso che per migliorare questa risposta potresti sostituire alcuni dei vari. Ai fini dell'apprendimento, penso che sia più facile da seguire, quando i tipi sono espressi chiaramente. Solo i miei 2 centesimi :)
Alex Baranosky,

3
Se ha il meglio dei due mondi, allora perché preoccuparsi di un dizionario?
Kyle Baran,

15
@KyleBaran: Perché sarebbe inutile per raccolte di coppie chiave / valore autentiche, dove esiste un solo valore per chiave.
Jon Skeet,

12
@KyleBaran Lookup<,>è semplicemente una raccolta immutabile (senza Addmetodo per es.) Che ha un uso limitato. Inoltre, non è una raccolta generica, nel senso che se si cerca una chiave inesistente si ottiene una sequenza vuota anziché un'eccezione, che è significativa solo in contesti speciali, ad esempio con linq. Questo va bene con il fatto che MS non ha fornito un costruttore pubblico per la classe.
nawfal,

La lettura dell'ordine delle risposte è jwg -> bobbymcr -> jonskeet
snr

58

Un modo di pensarci è questo: Lookup<TKey, TElement>è simile a Dictionary<TKey, Collection<TElement>>. Fondamentalmente un elenco di zero o più elementi può essere restituito tramite la stessa chiave.

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()); // 1
            Console.WriteLine("S's: {0}", namesByInitial['S'].Count()); // 2
            Console.WriteLine("Z's: {0}", namesByInitial['Z'].Count()); // 0, does not throw
        }
    }
}

2
Possono esserci zero elementi in un risultato di ricerca? Come lo otterresti? (La ricerca è pubblicamente immutabile per quanto posso dire, e non credo che ToLookup inventerebbe effettivamente le chiavi.)
Jon Skeet,

8
Tecnicamente sì, poiché una Ricerca restituisce una raccolta vuota per una chiave inesistente (ho modificato il mio post per aggiungere un esempio di codice che mostra questo).
Bobbymcr,

La lettura dell'ordine delle risposte è jwg -> bobbymcr -> jonskeet
snr

Una risposta molto chiara e utile, vorrei che fosse selezionata.
minuti

25

Un uso di Lookuppotrebbe essere quello di invertire a Dictionary.

Supponiamo di avere una rubrica implementata come Dictionarycon un gruppo di nomi (univoci) come chiavi, ogni nome associato a un numero di telefono. Ma due persone con nomi diversi potrebbero condividere lo stesso numero di telefono. Questo non è un problema per a Dictionary, a cui non importa che due chiavi corrispondano allo stesso valore.

Ora vuoi un modo per cercare a chi appartiene un determinato numero di telefono. Costruisci un Lookup, aggiungendo tutto KeyValuePairsdal tuo Dictionary, ma indietro, con il valore come chiave e la chiave come valore. Ora puoi eseguire una query su un numero di telefono e ottenere un elenco di nomi di tutte le persone il cui numero di telefono è. Costruire un Dictionarycon gli stessi dati eliminerebbe i dati (o fallire, a seconda di come lo hai fatto), dal momento che lo fai

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

significa che la seconda voce sovrascrive la prima - il Doc non è più elencato.

Cercare di scrivere gli stessi dati in un modo leggermente diverso:

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

genererebbe un'eccezione sulla seconda riga poiché non è possibile utilizzare Adduna chiave già presente in Dictionary.

[Ovviamente, potresti voler usare qualche altra singola struttura di dati per fare ricerche in entrambe le direzioni, ecc. Questo esempio significa che devi rigenerare Lookupda Dictionaryogni volta che quest'ultima cambia. Ma per alcuni dati potrebbe essere la soluzione giusta.]


La risposta è vitale per comprendere il concetto. +1. La lettura dell'ordine delle risposte è jwg -> bobbymcr -> jonskeet
snr

15

Non l'ho usato con successo prima, ma ecco il mio go:

A Lookup<TKey, TElement>si comporterebbe praticamente come un indice di database (relazionale) su una tabella senza un vincolo univoco. Usalo negli stessi posti in cui useresti l'altro.


5

Immagino che potresti discuterne in questo modo: immagina di creare una struttura di dati per contenere i contenuti di una rubrica. Si desidera digitare da lastName e quindi da firstName. L'uso di un dizionario qui sarebbe pericoloso perché molte persone possono avere lo stesso nome. Quindi un dizionario sarà sempre, al massimo, associato a un singolo valore.

Una ricerca verrà mappata su potenzialmente diversi valori.

Lookup ["Smith"] ["John"] sarà una raccolta di dimensioni di un miliardo.


La tua risposta ha ispirato la mia domanda di follow-up "Come ToLookup () con più indici?" . Come posso riprodurre tale, con più indici, la ricerca? Potresti rispondere eventualmente utilizzando qualsiasi altro campione o riferimento in cui è possibile utilizzare Lookup["Smith"]["John"] ?
Fulproof
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.