162 votes

Quel est l'intérêt de Lookup<TKey, TElement> ?

Le MSDN explique Lookup comme suit :

A Lookup<TKey, TElement> ressemble à un Dictionary<TKey, TValue> . La différence est qu'un Dictionnaire<TKey, TValue> fait correspondre des clés à des valeurs uniques, tandis qu'une Lookup<TKey, TElement> fait correspondre les clés à des collections de valeurs.

Je ne trouve pas cette explication particulièrement utile. À quoi sert la fonction Lookup ?

219voto

Jon Skeet Points 692016

C'est un croisement entre un IGrouping et un dictionnaire. Il vous permet de regrouper des éléments en fonction d'une clé, puis d'y accéder via cette clé de manière efficace (plutôt que d'itérer sur tous les éléments, comme c'est le cas avec le dictionnaire). GroupBy vous permet de le faire).

Par exemple, vous pouvez prendre un grand nombre de types .NET et construire une recherche par espace de noms... puis accéder très facilement à tous les types d'un espace de noms particulier :

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

(Normalement, j'utiliserais var pour la plupart de ces déclarations, en code normal).

61 votes

Je pense que pour améliorer cette réponse, vous pourriez remplacer certaines variables. Pour l'apprentissage, je pense qu'il est plus facile de suivre, lorsque les types sont exprimés clairement. Juste mes deux centimes :)

3 votes

S'il a le meilleur des deux mondes, alors pourquoi s'embêter avec un dictionnaire ?

16 votes

@KyleBaran : Parce que ce serait inutile pour les véritables collections de paires clé/valeur, où il n'y a qu'une seule valeur par clé.

63voto

bobbymcr Points 14916

Une façon d'y penser est la suivante : Lookup<TKey, TElement> est similaire à Dictionary<TKey, Collection<TElement>> . En principe, une liste de zéro ou plusieurs éléments peut être renvoyée via la même clé.

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 votes

Peut-il y avoir zéro élément dans un résultat de consultation ? Comment l'obtenir ? (Lookup est publiquement immuable pour autant que je puisse dire, et je ne pense pas que ToLookup inventerait effectivement des clés).

9 votes

Techniquement, oui, puisqu'un Lookup renvoie une collection vide pour une clé inexistante (j'ai modifié mon message pour ajouter un exemple de code qui montre cela).

0 votes

L'ordre de lecture des réponses est jwg -> bobbymcr -> jonskeet

28voto

jwg Points 53

Une utilisation de Lookup pourrait être d'inverser un Dictionary .

Supposons que vous ayez un répertoire téléphonique implémenté en tant que Dictionary avec un tas de noms (uniques) comme clés, chaque nom étant associé à un numéro de téléphone. Mais deux personnes ayant des noms différents peuvent partager le même numéro de téléphone. Ce n'est pas un problème pour un Dictionary qui ne se soucie pas que deux clés correspondent à la même valeur.

Maintenant, vous voulez un moyen de chercher à qui appartient un numéro de téléphone donné. Vous construisez un Lookup en ajoutant tous les KeyValuePairs de votre Dictionary mais à l'envers, avec la valeur comme clé et la clé comme valeur. Vous pouvez maintenant interroger un numéro de téléphone et obtenir une liste de noms de toutes les personnes dont c'est le numéro de téléphone. Construire un Dictionary avec les mêmes données perdrait les données (ou échouerait, selon la façon dont vous l'avez fait), puisque le fait de faire

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

signifie que la deuxième entrée écrase la première - le Doc n'est plus répertorié.

J'essaie d'écrire les mêmes données d'une manière légèrement différente :

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

jetterait une exception sur la deuxième ligne puisque vous ne pouvez pas Add une clé qui se trouve déjà dans le Dictionary .

[Bien entendu, vous pouvez utiliser une autre structure de données unique pour effectuer des recherches dans les deux sens, etc. Cet exemple signifie que vous devez régénérer le fichier Lookup de la Dictionary chaque fois que ce dernier change. Mais pour certaines données, cela pourrait être la bonne solution].

0 votes

La réponse est essentielle pour comprendre le concept. +1. L'ordre de lecture des réponses est jwg -> bobbymcr -> jonskeet

15voto

Daren Thomas Points 26812

Je ne l'ai pas encore utilisé avec succès, mais voici mon essai :

A Lookup<TKey, TElement> se comporterait à peu près comme un index de base de données (relationnel) sur une table sans contrainte unique. Utilisez-le aux mêmes endroits que vous utiliseriez l'autre.

5voto

David Andres Points 13569

Je suppose que l'on pourrait argumenter de la façon suivante : imaginez que vous créez une structure de données pour contenir le contenu d'un annuaire téléphonique. Vous souhaitez effectuer des recherches par nom de famille, puis par prénom. L'utilisation d'un dictionnaire serait dangereuse car de nombreuses personnes peuvent avoir le même nom. Un dictionnaire correspondra donc toujours, au maximum, à une seule valeur.

Une Lookup peut potentiellement correspondre à plusieurs valeurs.

Lookup["Smith"]["John"] sera une collection de taille un milliard.

0 votes

Votre réponse a inspiré ma question complémentaire "Comment ToLookup() avec des index multiples ?" . Comment puis-je reproduire un tel lookup, avec des index multiples ? Pourriez-vous y répondre éventuellement en utilisant un autre exemple ou une autre référence où il est possible d'utiliser Lookup["Smith"]["John"] ?

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X