50 votes

Python OrderedDict ne garde pas l'ordre des éléments

J'essaie de créer un objet OrderedDict mais dès que je le crée, les éléments sont tous mélangés.

C'est ce que je fais :

from collections import OrderedDict
od = OrderedDict({(0,0):[2],(0,1):[1,9],(0,2):[1,5,9]})

Les éléments ne restent pas dans l'ordre que j'ai assigné.

od
OrderedDict([((0, 1), [1, 9]), ((0, 0), [2]), ((0, 2), [1, 5, 9])])

Le site docs.python.org ne contient pas d'exemple et je n'arrive pas à comprendre pourquoi l'ordre est mélangé. Toute aide est la bienvenue.

92voto

Lattyware Points 37257

Votre problème est que vous construisez un dict pour donner les données initiales à la OrderedDict - ce dict n'a pas stocker tout ordre, donc l'ordre est perdu avant qu'il n'arrive à la OrderedDict .

La solution consiste à construire à partir d'un type de données ordonné - le plus simple étant un list de tuple s :

>>> from collections import OrderedDict
>>> od = OrderedDict([((0, 0), [2]), ((0, 1), [1, 9]), ((0, 2), [1, 5, 9])])
>>> od
OrderedDict([((0, 0), [2]), ((0, 1), [1, 9]), ((0, 2), [1, 5, 9])])

Il est intéressant de noter que c'est pourquoi OrderedDict utilise la syntaxe qu'il utilise pour sa représentation de chaîne de caractères - les représentations de chaînes de caractères devraient essayer d'être du code Python valide pour reproduire l'objet lorsque cela est possible, et c'est pourquoi la sortie utilise une liste de tuples au lieu d'un dict.

Edita: À partir de Python 3.6, kwargs est ordonné Vous pouvez donc utiliser des arguments sous forme de mots-clés à la place, à condition que vous disposiez d'une version de Python à jour.

A partir de 3.7 c'est également le cas pour dict (c'était le cas pour CPython en 3.6, mais les spécifications du langage ne le spécifiaient pas, donc l'utilisation de OrderedDict était encore nécessaire pour la compatibilité). Cela signifie que si vous pouvez supposer un environnement 3.7+, vous pouvez souvent laisser tomber OrderedDict ou en construire un à partir d'un modèle régulier de dict si vous avez besoin d'une fonction spécifique (par exemple, l'ordre d'importance pour l'égalité).

12 votes

Il faut également noter que le fait de passer des noms/valeurs au constructeur ne suffit pas à définir l'ordre. >>> from collections import OrderedDict >>> OrderedDict(one=1, two=2, three=3, four=4) OrderedDict([('four', 4), ('one', 1), ('three', 3), ('two', 2)])

1 votes

@EricSmith En effet, pour la même raison - les args de mots-clés variables ( **kwargs ) en Python sont stockés sous forme de dictionnaire - donc lorsque cela se produit, l'ordre est perdu comme avant. Notez que PEP-468 a une solution simple à ce problème : utiliser un OrderedDict para kwargs Ce n'est pas encore une fonctionnalité, mais peut-être un jour.

2 votes

@GarethLatty maintenant en python 3.6 ils ont mis en œuvre le PEP-468

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