La bonne façon d'initialiser un OrderedDict en utilisant son constructeur de telle sorte qu'il conserve l'ordre des données initiales?

124

Quelle est la bonne façon d'initialiser un dictionnaire ordonné (OD) afin qu'il conserve l'ordre des données initiales?

from collections import OrderedDict

# Obviously wrong because regular dict loses order
d = OrderedDict({'b':2, 'a':1}) 

# An OD is represented by a list of tuples, so would this work?
d = OrderedDict([('b',2), ('a', 1)])

# What about using a list comprehension, will 'd' preserve the order of 'l'
l = ['b', 'a', 'c', 'aa']
d = OrderedDict([(i,i) for i in l])

Question:

  • Est-ce qu'une OrderedDictconservation de l'ordre d'une liste de tuples, ou d'un tuple de tuples ou d'un tuple de listes ou d'une liste de listes etc. passée au moment de l'initialisation (2ème et 3ème exemple ci-dessus)?

  • Comment vérifier si OrderedDictune commande est effectivement maintenue? Puisque a dicta un ordre imprévisible, que se passe-t-il si mes vecteurs de test ont heureusement le même ordre initial que l'ordre imprévisible d'un dict? Par exemple, si au lieu d' d = OrderedDict({'b':2, 'a':1})écrire d = OrderedDict({'a':1, 'b':2}), je peux conclure à tort que l'ordre est conservé. Dans ce cas, j'ai découvert que a dictest classé par ordre alphabétique, mais ce n'est peut-être pas toujours vrai. Quel est un moyen fiable d'utiliser un contre-exemple pour vérifier si une structure de données préserve l'ordre ou non, à moins d'essayer des vecteurs de test à plusieurs reprises jusqu'à ce que l'on casse?

PS Je vais juste laisser ceci ici pour référence : "Le constructeur OrderedDict et la méthode update () acceptent tous les deux des arguments de mots-clés, mais leur ordre est perdu car la fonction de Python appelle les arguments de mots-clés de la sémantique à l'aide d'un dictionnaire non ordonné régulier."

PPS: J'espère qu'à l'avenir, OrderedDict conservera également l'ordre des kwargs (exemple 1): http://bugs.python.org/issue16991

Cliquez sur
la source
10
Il est vaguement ironique que l'initialisation d'un OrderedDict avec un dict (non vide) est la mauvaise chose à faire ... sans doute cela devrait entraîner un avertissement car il viole probablement l'intention de l'utilisateur.
smci
3
Après python3.6, OrderDict(b=2, a=1)c'est aussi un bon moyen. Voir PEP 468 .
IvanaGyro

Réponses:

90

OrderedDict conservera toute commande à laquelle il a accès. La seule façon de lui passer des données ordonnées à initialiser est de passer une liste (ou, plus généralement, un itérable) de paires clé-valeur, comme dans vos deux derniers exemples. Comme le dit la documentation que vous avez liée, OrderedDict n'a accès à aucun ordre lorsque vous passez des arguments de mot-clé ou un argument dict, car tout ordre y est supprimé avant que le constructeur OrderedDict ne le voie.

Notez que l'utilisation d'une compréhension de liste dans votre dernier exemple ne change rien. Il n'y a aucune différence entre OrderedDict([(i,i) for i in l])et OrderedDict([('b', 'b'), ('a', 'a'), ('c', 'c'), ('aa', 'aa')]). La compréhension de la liste est évaluée et crée la liste et elle est transmise; OrderedDict ne sait rien de la façon dont il a été créé.

BrenBarn
la source
74
# An OD is represented by a list of tuples, so would this work?
d = OrderedDict([('b', 2), ('a', 1)])

Oui, cela fonctionnera. Par définition, une liste est toujours ordonnée de la manière dont elle est représentée. Cela vaut aussi pour la compréhension de liste, la liste générée est de la même manière que les données ont été fournies (c'est-à-dire que la source d'une liste sera déterministe, issue d'un setou dictpas tellement).

Comment vérifier si OrderedDictune commande est effectivement maintenue? Puisqu'un dict a un ordre imprévisible, que se passe-t-il si mes vecteurs de test ont heureusement le même ordre initial que l'ordre imprévisible d'un dict ?. Par exemple, si au lieu d' d = OrderedDict({'b':2, 'a':1})écrire d = OrderedDict({'a':1, 'b':2}), je peux conclure à tort que l'ordre est conservé. Dans ce cas, j'ai découvert que a dictest dans l'ordre alphabétique, mais ce n'est peut-être pas toujours vrai. c'est-à-dire quelle est une manière fiable d'utiliser un exemple de compteur pour vérifier si une structure de données préserve l'ordre ou pas à court d'essayer des vecteurs de test à plusieurs reprises jusqu'à ce que l'on casse.

Vous conservez votre liste source de 2-tuple pour référence et vous l'utilisez comme données de test pour vos cas de test lorsque vous effectuez des tests unitaires. Parcourez-les et assurez-vous que l'ordre est maintenu.

metatoaster
la source
À propos de la vérification de l'ordre: Comment puis-je m'assurer que mon 2-tuple va casser l'ordre de dict s'il est imprévisible? C'est une question générique sur toute structure de données, peut-être devrais-je la séparer de cette question.
cliquez sur
1
Vous ne pouvez pas casser de manière déterministe quelque chose qui n'est pas de nature déterministe.
metatoaster
1
Alors, quelle est la bonne approche pour tester de telles choses? Vous continuez d'essayer indéfiniment? L'ordre est imprévisible pour les programmeurs, mais comme il s'agit d'une carte de hachage, il suit `` un '' algorithme et un bon test devrait essayer de contrer cela?
cliquez sur
2
Voir __hash__. Plus précisément sur le strtype.
metatoaster
Par définition, une liste est toujours ordonnée de la manière dont elle est représentée. C'était une déclaration clé pour moi. J'ai décidé d'utiliser simplement une liste de 2-tuples pour mon élément de base OrderedDictafin de ne pas avoir la charge de convertir une liste en fichier OrderedDict. Je fais une boucle sur les éléments comme une liste au lieu d'un dictionnaire.
Bobort