Dictionnaire vs liste

30

J'ai donc rencontré un Dictionary<int, int>aujourd'hui au travail. Cela me semblait juste bizarre parce que j'aurais probablement juste utilisé un à la List<int>place. Y a-t-il une différence et y aurait-il un cas d'utilisation où une structure serait préférée à l'autre?

ZeroDivide
la source
1
Doit-il y avoir une relation entre deux (ou plus) ints donnés? Ensuite, la carte (dictionnaire dans cette langue) prend tout son sens.
Rig
3
Le dictionnaire des noms me le rend évident. Lorsque vous devez rechercher quelque chose rapidement, vous utilisez un dictionnaire.
ChaosPandion
2
@ChaosPandion: a List<T>dans le framework .NET est un tableau à accès aléatoire, où une opération de recherche est généralement plus rapide que pour a Dictionary<int,T>.
Doc Brown
2
@DocBrown - Seulement dans le cas assez étrange de l'utilisation de l'index numérique comme clé. Sinon, une recherche sera plus rapide lors de l'utilisation Dictionary<TKey, TValue>.
ChaosPandion
2
@chaos cette question concerne ce cas étrange.
MarkJ

Réponses:

32

Vous utiliseriez un Dictionary<int, int>si vos index ont une signification spéciale en plus du placement positionnel.

L'exemple immédiat qui me vient à l'esprit est le stockage d'une colonne id et d'une colonne int dans une base de données. Par exemple, si vous avez une [person-id]colonne et une [personal-pin]colonne, vous pouvez les intégrer dans un fichier Dictionary<int, int>. De cette façon, pinDict[person-id]vous donne un code PIN, mais l'indice est significatif et pas seulement une position dans un List<int>.

Mais vraiment, chaque fois que vous avez deux listes d'entiers liées, cela pourrait être une structure de données appropriée.

Kris Harper
la source
Si mon identifiant personnel est compris entre 0, ..., 999 et que je devrais charger les valeurs des broches personnelles en mémoire pour les 1000 personnes, je choisirais généralement un List<int>, et non un dictionnaire. Voir ma réponse ci-dessous.
Doc Brown
3
oui mais un dictionnaire peut être rare
jk.
@jk: c'est exactement ce que j'ai essayé d'élaborer dans ma réponse.
Doc Brown
7
Code PIN personnel? Cela semble un peu redondant.
Jack
Hm, lorsque l'indice a "une signification spéciale", dans des scénarios réels, il est probable qu'ils ne forment pas une plage contiguë [0, ..., n] (bien que ce ne soit pas obligatoire), donc cette réponse est pas tout à fait faux, mais imprécis. Néanmoins, à mon humble avis, la décision ne doit pas être basée sur cette "chose ayant une signification particulière", mais uniquement sur "les clés construisent-elles approximativement un intervalle [0, ..., n]". Sur la base du nombre de votes positifs, je suppose que la plupart des lecteurs ont raté ce point.
Doc Brown
28

Considérez le Listcomme un tableau et Dictionarycomme une table de hachage . Vous utiliseriez uniquement le Dictionarysi vous aviez besoin de mapper (ou d'associer) des clés significatives à des valeurs, tandis qu'un Listseul mappe (ou associe) des positions (ou des indices) à des valeurs.

Par exemple, supposons que vous vouliez enregistrer une association entre l'âge d'une personne et sa taille. Vous pouvez utiliser un Dictionary<int, int>pour mapper l'âge (an int) de la personne à sa taille (an int):

Dictionary<int, int> personHeightMap = new Dictionary<int, int>();

personHeightMap.Add(21, 185);
personHeightMap.Add(31, 174);

int height = personHeightMap.ContainsKey(21) ? personHeightMap[21] : -1;

Ce n'est pas un exemple très utile, mais le fait est que vous ne pourriez pas faire cela aussi élégamment avec un Listcar il aurait besoin de stocker ces valeurs positionnellement.

Bernard
la source
7
+1 pour avoir mentionné qu'un Listtraite avec ordre , où un Dictionarytraite avec association . Si vous avez besoin d'obtenir vos données dans un certain ordre à chaque fois, ou si leur ordre les uns par rapport aux autres est important, Listc'est la voie à suivre. Dictionariesont tendance à ne pas être ordonnées et traitent des relations clés -> valeur.
KChaloux
2
Enfin et surtout, lorsque vous savez ce que vous recherchez, la table de hachage est environ O (1), tandis que le tableau est O (logN) dans le meilleur des cas (triés et sans doublons) et O (N) dans le pire des cas.
JensG
1
+1. Personne d'autre ne semble avoir abordé le point selon lequel les listes sont sémantiquement ordonnées et les dict sont des recherches sémantiques, ce qui est absolument fondamental , à mon avis.
Benjamin Hodgson
15

Sémantiquement, a Dictionary<int, T>et List<T>sont très similaires, les deux sont des conteneurs à accès aléatoire du framework .NET. Pour utiliser une liste en remplacement d'un dictionnaire, vous avez besoin d'une valeur spéciale dans votre type T(comme null) pour représenter les emplacements vides dans votre liste. Si Tn'est pas un type nullable comme int, vous pouvez utiliser à la int?place, ou si vous vous attendez à stocker des valeurs positives, vous pouvez également utiliser une valeur spéciale comme -1 pour représenter les emplacements vides.

Lequel vous choisirez devrait dépendre de la plage des valeurs clés. Si vos clés dans le Dictionary<int, T>sont dans un intervalle entier, sans beaucoup d'espaces entre elles (par exemple, 80 valeurs sur [0, ... 100]), alors a List<T>sera plus approprié, car l'accès par index est plus rapide, et il y a moins de mémoire et de temps par rapport à un dictionnaire dans ce cas.

Si vos valeurs clés sont 100 intvaleurs d'une plage comme [0, ..., 1000000], alors a a List<T>besoin de mémoire pour contenir 1000000 valeurs de T, où votre dictionnaire aura juste besoin de mémoire dans un ordre de grandeur autour de 100 valeurs de T, 100 valeurs de int (plus une surcharge, en réalité, attendez environ 2 fois la mémoire pour stocker ces 100 clés et valeurs). Dans ce dernier cas, un dictionnaire sera donc plus approprié.

Doc Brown
la source
6
c'est la différence importante à mon humble avis, Dictionary <int, int> peut être rare
jk.
Dans ce cas, ne pouvons-nous pas utiliser List <KeyValuePair <int, int >>? Lequel serait le mieux pour une traversée linéaire?
Deepak Mishra
@DeepakMishra: la principale différence ici est List<KeyValuePair<int,T>>qu'il n'y a pas d'opération de recherche O (1) disponible. Deuxièmement, les éléments dans List<KeyValuePair<int,T>>peuvent avoir un ordre spécifique, indépendant de leurs valeurs clés. Si vous avez besoin de ce dernier mais pas du premier, List<KeyValuePair<int,T>>ou List<Tuple<int,T>>pourrait être le meilleur choix. Si vous avez besoin des deux, il y en a aussi OrderedDictionary.
Doc Brown
@DocBrown Laquelle serait la meilleure pour la traversée linéaire (c'est-à-dire foreach) et l'opération d'insertion, pas besoin de recherche directe?
Deepak Mishra
@DeepakMishra: il n'y a rien de tel que "généralement mieux" dans le développement de logiciels. Mieux ici pourrait signifier plus rapidement, mieux lire, moins de code à taper, plus facile à étendre pour les exigences à venir. Mais en général, arrêtez de penser à cela, mettez en œuvre celui qui résout correctement votre problème et qui est le plus simple à vos yeux , vérifiez s'il est assez rapide pour votre objectif et n'y investissez plus de réflexion lorsque vous observez des inconvénients.
Doc Brown
6

Comment peut-on les considérer comme équivalents?

Le dictionnaire est clairsemé et permet des insertions aléatoires, mais rend la traversée dans l'ordre un problème, la liste n'est pas clairsemée et une insertion dans le désordre est coûteuse, elle fournit par nature une traversée dans l'ordre.

Il y aurait très peu de situations où l'une n'était pas dramatiquement supérieure à l'autre.

Loren Pechtel
la source
2

À part: D'autres langages de programmation se réfèrent à ce type de structure de données comme une carte, plutôt qu'un dictionnaire.

Si vos données peuvent être définies de manière significative en tant que paires clé / valeur, un dictionnaire fournira un accès beaucoup plus rapide si vous avez besoin de trouver une valeur à l'aide de sa clé.

Par exemple, supposons que vous ayez une liste de clients. Chaque client comprend des détails tels qu'un nom et une adresse, ainsi qu'un numéro de client unique. Supposons que vous ayez également une liste des commandes en cours de traitement. Chaque commande contiendra des détails sur ce qui est fait et devra inclure le numéro de client de la personne qui l'a commandée.

Lorsqu'une commande est prête à être expédiée, vous devez trouver l'adresse de livraison. Si les clients sont stockés sous forme de liste simple, vous devez rechercher dans la liste entière pour trouver le client avec le bon numéro de client. Au lieu de cela, vous pouvez stocker les clients dans un dictionnaire, avec le numéro de client comme clé. Le dictionnaire vous permet désormais de retirer le bon client en une seule étape sans aucune recherche.

Simon B
la source
1

Le dictionnaire utilise le hachage pour rechercher les données. Un dictionnaire a d'abord calculé une valeur de hachage pour la clé et cette valeur de hachage conduit au compartiment de données cible. Après cela, chaque élément du compartiment doit être vérifié pour l'égalité. Mais en fait, la liste sera plus rapide que le dictionnaire lors de la recherche du premier élément car rien à rechercher dans la première étape. Mais dans la deuxième étape, la liste doit parcourir le premier élément, puis le deuxième élément. Ainsi, à chaque étape, la recherche prend de plus en plus de temps. Plus la liste est grande, plus elle prend de temps.

En savoir plus sur .... Dictionnaire Vs List avec exemple.

Walshregal
la source
-1

Si le code en question stocke deux ensembles de valeurs corrélées, la classe Dictionary fournit un moyen indexé de rechercher des valeurs par une clé. S'il n'y a qu'un seul ensemble de valeurs, mais que cet ensemble doit être consulté de manière aléatoire (peut-être pour vérifier l'existence d'une clé dans un ensemble), et que les valeurs sont uniques, un HashSet pourrait être la meilleure classe d'ensemble à utiliser.

JoshL
la source
-3

Ce sont d'excellentes réponses qui semblent couvrir les bases.

Une autre considération que je proposerai est que les dictionnaires (en C #) sont plus complexes du point de vue du codage. Avoir à la fois des listes et des dictionnaires dans la même base de code rend votre code plus difficile à maintenir dans la mesure où les deux méthodes ont des différences subtiles dans la façon d'effectuer des opérations de base telles que la recherche et le rassemblement de données d'objets. À mon avis, sauf si vous avez besoin d'un dictionnaire pour une raison valable, utilisez une liste.

StephenR
la source
8
Je ne suis pas d'accord. Le dictionnaire / la carte est une structure de données fondamentale que chaque ingénieur logiciel doit connaître intimement. Quoi qu'il en soit: vous auriez besoin d'une raison justifiable pour utiliser n'importe quelle structure de données; y compris la liste.
Steven Evers