L'ordre des éléments dans le dictionnaire

107

Ma question concerne l'énumération des éléments du dictionnaire

// Dictionary definition
private Dictionary<string, string> _Dictionary = new Dictionary<string, string>();

// add values using add

_Dictionary.Add("orange", "1");
_Dictionary.Add("apple", "4");
_Dictionary.Add("cucumber", "6");

// add values using []

_Dictionary["banana"] = 7;
_Dictionary["pineapple"] = 7;

// Now lets see how elements are returned by IEnumerator
foreach (KeyValuePair<string, string> kvp in _Dictionary)
{
  Trace.Write(String.Format("{0}={1}", kvp.Key, kvp.Value));
}

Dans quel ordre les éléments seront-ils énumérés? Puis-je forcer l'ordre à être alphabétique?

Capitaine Comic
la source

Réponses:

125

L'ordre des éléments dans un dictionnaire n'est pas déterministe. La notion d'ordre n'est tout simplement pas définie pour les tables de hachage. Ne vous fiez donc pas à l'énumération dans le même ordre que les éléments ont été ajoutés au dictionnaire. Ce n'est pas garanti.

Citation du doc :

À des fins d'énumération, chaque élément du dictionnaire est traité comme une KeyValuePair<TKey, TValue>structure représentant une valeur et sa clé. L'ordre dans lequel les articles sont retournés n'est pas défini.

Darin Dimitrov
la source
1
Mais il y a OrderedDictionary .
Peter Mortensen
28

Si vous voulez que les éléments soient classés, utilisez un OrderedDictionary . Un dictionnaire / dictionnaire hastable ordinaire n'est ordonné que dans un certain sens de la disposition de stockage.

Blé Mitch
la source
10
OrderedDictionary est dans la plupart des cas faux. Il n'est ni trié par clé ni par valeur, mais par un index interne. SortedDictionary est celui qui est ordonné d'une manière que l'utilisateur peut manipuler (clé par défaut)
Offler
3
La question se pose sur l'ordre alphabétique (en supposant que le questionneur parle de la clé). Un dictionnaire ordonné, si je comprends bien la documentation, crachera les éléments dans l'ordre dans lequel ils sont insérés, c'est-à-dire pas par ordre alphabétique, mais en utilisant l'index interne. Un SortedDictionary est probablement la meilleure solution pour la question de l'utilisateur.
matpm
28

Vous pouvez toujours utiliser SortedDictionarypour cela. Notez que le dictionnaire est trié par clé, par défaut, sauf si un comparateur a été spécifié.

Je suis sceptique quant à l'utilisation de OrderedDictionarypour ce que vous voulez puisque la documentation dit que:

Les éléments d'un OrderedDictionary ne sont pas triés par la clé, contrairement aux éléments d'une classe SortedDictionary.

Adriano Carneiro
la source
Il est important de noter qu'il SortedDictionary<K,V>est implémenté en tant qu'arbre de recherche binaire, ce qui donne à ses opérations une complexité temporelle et spatiale différente de celle basée sur la table de hachage Dictionary<K,V>. Si les utilisateurs ont besoin d'une O(1)structure de table de hachage d'insertion / suppression et souhaitent également parcourir les éléments dans l'ordre des clés, ils devraient à la dict.Keys.OrderBy( k => k ).Select( k => dict[k] )place (au prix de l' O(n)espace et du O( n log n )temps) pour le OrderBy()(qui devra mettre en mémoire tampon toute la collection de clés dans une liste interne ).
Dai
12

Les éléments seront retournés dans l'ordre dans lequel ils ont été stockés physiquement dans le dictionnaire, qui dépend du code de hachage et de l'ordre dans lequel les éléments ont été ajoutés. Ainsi, l'ordre semblera aléatoire, et à mesure que les implémentations changent, vous ne devriez jamais dépendre du fait que l'ordre reste le même.

Vous pouvez commander les éléments lors de leur énumération:

foreach (KeyValuePair<string, string> kvp in _Dictionary.OrderBy(k => k.Value)) {
  ...
}

Dans le framework 2.0, vous devez d'abord mettre les éléments dans une liste afin de les trier:

List<KeyValuePair<string, string>> items = new List<KeyValuePair<string, string>>(_Dictionary);
items.Sort(delegate(KeyValuePair<string, string> x, KeyValuePair<string, string> y) { return x.Value.CompareTo(y.Value); });
foreach (KeyValuePair<string,string> kvp in items) {
  ...
}
Guffa
la source
11

Pour un OrderedDictionary:

 var _OrderedDictionary = new System.Collections.Specialized.OrderedDictionary();

_OrderedDictionary.Add("testKey1", "testValue1");
_OrderedDictionary.Add("testKey2", "testValue2");
_OrderedDictionary.Add("testKey3", "testValue3");

var k = _OrderedDictionary.Keys.GetEnumerator();
var v = _OrderedDictionary.Values.GetEnumerator();

while (k.MoveNext() && v.MoveNext()) {
    var key = k.Current; var value = v.Current;
}

Les articles sont retournés dans l'ordre dans lequel ils ont été ajoutés.

Barton
la source
5

Les tableaux associatifs (aka, tables de hachage) ne sont pas ordonnés, ce qui signifie que les éléments peuvent être ordonnés de n'importe quelle manière imaginable.

CEPENDANT, vous pouvez récupérer les clés du tableau (uniquement les clés), les classer par ordre alphabétique (via une fonction de tri), puis travailler dessus.

Je ne peux pas vous donner d'exemple C # car je ne connais pas le langage, mais cela devrait suffire pour que vous puissiez continuer vous-même.

Tim Čas
la source