Le MSDN explique Lookup comme ceci:
UNE
Lookup<TKey, TElement>
ressemble à unDictionary<TKey, TValue>
. La différence est qu'un dictionnaire <TKey, TValue> mappe les clés sur des valeurs uniques, alors qu'un Lookup <TKey, TElement> mappe les clés sur des collections de valeurs.
Je ne trouve pas cette explication particulièrement utile. À quoi sert Lookup?
C'est un croisement entre un IGrouping
et un dictionnaire. Il vous permet de regrouper des éléments à l'aide d'une clé, mais d'y accéder de manière efficace via cette clé (plutôt que de simplement les parcourir tous, comme le permet GroupBy
.).
Par exemple, vous pouvez prendre une charge de types .NET et créer une recherche par espace de noms ... puis accéder à tous les types d'un espace de noms particulier très facilement:
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);
}
}
}
(J'utiliserais normalement var
pour la plupart de ces déclarations, en code normal.)
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
}
}
}
Une utilisation de Lookup
pourrait consister à inverser un Dictionary
.
Supposons que vous avez un répertoire implémenté en tant que Dictionary
avec un groupe de noms (uniques) comme clés, chaque nom associé à un numéro de téléphone. Mais deux personnes avec 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 se moque que deux clés correspondent à la même valeur.
Maintenant, vous voulez un moyen de rechercher à qui appartient un numéro de téléphone donné. Vous construisez un Lookup
, en ajoutant tous les KeyValuePairs
de votre Dictionary
, mais en arrière, 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 des noms de toutes les personnes dont le numéro de téléphone est. Construire un Dictionary
avec les mêmes données lâcherait des données (ou échouerait, selon ce que vous avez fait), car
dictionary["555-6593"] = "Dr. Emmett Brown";
dictionary["555-6593"] = "Marty McFly";
signifie que la deuxième entrée remplace la première - le document n'est plus répertorié.
Essayer 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 car vous ne pouvez pas Add
une clé qui se trouve déjà dans le Dictionary
.
[Bien sûr, 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 Lookup
à partir du Dictionary
à chaque fois que ce dernier changements. Mais pour certaines données, cela pourrait être la bonne solution.]
Je ne l'ai pas utilisé avec succès auparavant, mais voici mon tour:
UNE Lookup<TKey, TElement>
se comporterait presque comme un index de base de données (relationnelle) sur une table sans contrainte unique. Utilisez-le aux mêmes endroits que vous utiliseriez l'autre.
Je suppose que vous pourriez le dire de la manière suivante: imaginez que vous créez une structure de données pour contenir le contenu d'un annuaire téléphonique. Vous voulez saisir par nom, puis par prénom. Utiliser un dictionnaire ici serait dangereux car beaucoup de gens peuvent avoir le même nom. Ainsi, un dictionnaire sera toujours, au plus, mappé à une valeur unique.
Une recherche mappera potentiellement plusieurs valeurs.
Lookup ["Smith"] ["John"] constituera une collection d'un milliard.