161 votes

Conversion de dict en OrderedDict

J'ai des difficultés à utiliser le collections.OrderedDict la classe. J'utilise Python 2.7 sur Raspbian, la distribution Debian pour Raspberry Pi. J'essaie d'imprimer deux dictionnaires dans l'ordre pour les comparer (côte à côte) dans le cadre d'une aventure textuelle. L'ordre est essentiel pour pouvoir comparer avec précision. Peu importe ce que j'essaie, les dictionnaires s'impriment dans leur ordre habituel.

Voici ce que j'obtiens lorsque je le fais sur mon RPi :

import collections

ship = {"NAME": "Albatross",
         "HP":50,
         "BLASTERS":13,
         "THRUSTERS":18,
         "PRICE":250}

ship = collections.OrderedDict(ship)

print ship
# OrderedDict([('PRICE', 250), ('HP', 50), ('NAME', 'Albatross'), ('BLASTERS', 13), ('THRUSTERS', 18)])

Il y a manifestement quelque chose qui ne va pas car il imprime l'appel de fonction et met les clés et les groupes de valeurs dans une liste imbriquée...

C'est ce que j'ai obtenu en exécutant quelque chose de similaire sur mon PC :

import collections

Joe = {"Age": 28, "Race": "Latino", "Job": "Nurse"}
Bob = {"Age": 25, "Race": "White", "Job": "Mechanic", "Random": "stuff"}

#Just for clarity:
Joe = collections.OrderedDict(Joe)
Bob = collections.OrderedDict(Bob)

print Joe
# OrderedDict([('Age', 28), ('Race', 'Latino'), ('Job', 'Nurse')])
print Bob
# OrderedDict([('Age', 25), ('Race', 'White'), ('Job', 'Mechanic'), ('Random', 'stuff')])

Cette fois, c'est en ordre, mais ça ne devrait pas imprimer les autres choses, non ? (La mise dans la liste et l'appel de la fonction d'affichage).

Où est-ce que je fais mon erreur ? Cela ne devrait pas avoir de rapport avec la version pi de Python car il s'agit simplement de la version Linux.

240voto

Martijn Pieters Points 271458

Vous créez un dictionnaire primero puis de transmettre ce dictionnaire à un OrderedDict . Pour les versions de Python < 3.6 (*) le temps que vous fassiez cela, la commande ne sera plus correcte. dict n'est pas ordonnée par nature.

Passez dans une séquence de tuples à la place :

ship = [("NAME", "Albatross"),
        ("HP", 50),
        ("BLASTERS", 13),
        ("THRUSTERS", 18),
        ("PRICE", 250)]
ship = collections.OrderedDict(ship)

Ce que vous voyez lorsque vous imprimez le OrderedDict est c'est représentation et c'est tout à fait correct. OrderedDict([('PRICE', 250), ('HP', 50), ('NAME', 'Albatross'), ('BLASTERS', 13), ('THRUSTERS', 18)]) vous montre juste, dans un reproductible représentation, quel est le contenu de la OrderedDict .


(*) : Dans l'implémentation de CPython 3.6, la fonction dict a été mis à jour pour utiliser une structure interne plus efficace en termes de mémoire, qui a l'heureux effet secondaire de préserver l'ordre d'insertion, et par extension le code montré dans la question fonctionne sans problème. À partir de Python 3.7, le type Spécification du langage Python a été mis à jour pour exiger que toutes les implémentations Python suivent ce comportement. Voir cette autre réponse de ma part pour plus de détails et aussi pourquoi vous voudriez toujours utiliser une OrderedDict() pour certains cas.

41voto

Jan Rozycki Points 402

Si vous ne pouvez pas modifier cette partie du code où votre dict a été défini, vous pouvez quand même le commander à n'importe quel moment de la manière que vous voulez, comme ceci :

from collections import OrderedDict

order_of_keys = ["key1", "key2", "key3", "key4", "key5"]
list_of_tuples = [(key, your_dict[key]) for key in order_of_keys]
your_dict = OrderedDict(list_of_tuples)

12voto

Abdul Majeed Points 2275

La plupart du temps, nous choisissons OrderedDict lorsque nous avons besoin d'un ordre personnalisé et non d'un ordre générique comme ASC, etc.

Voici la solution proposée :

import collections
ship = {"NAME": "Albatross",
         "HP":50,
         "BLASTERS":13,
         "THRUSTERS":18,
         "PRICE":250}

ship = collections.OrderedDict(ship)

print ship

new_dict = collections.OrderedDict()
new_dict["NAME"]=ship["NAME"]
new_dict["HP"]=ship["HP"]
new_dict["BLASTERS"]=ship["BLASTERS"]
new_dict["THRUSTERS"]=ship["THRUSTERS"]
new_dict["PRICE"]=ship["PRICE"]

print new_dict

Ce sera la sortie :

OrderedDict([('PRICE', 250), ('HP', 50), ('NAME', 'Albatross'), ('BLASTERS', 13), ('THRUSTERS', 18)])
OrderedDict([('NAME', 'Albatross'), ('HP', 50), ('BLASTERS', 13), ('THRUSTERS', 18), ('PRICE', 250)])

Note : Les nouveaux dictionnaires triés conservent leur ordre de tri lorsque des entrées sont supprimées. Mais lorsque de nouvelles clés sont ajoutées, celles-ci sont ajoutées à la fin et le tri n'est pas maintenu.( document officiel )

6voto

Vous pouvez créer le dict ordonné à partir de l'ancien dict en une seule ligne :

from collections import OrderedDict
ordered_dict = OrderedDict(sorted(ship.items())

La clé de tri par défaut est la clé du dictionnaire, donc la nouvelle fonction ordered_dict est trié par les clés de l'ancien dict.

1voto

Mohammad-Ali Points 143

Utilisez dict.items() ; cela peut être aussi simple que ce qui suit :

ship = collections.OrderedDict(ship.items())

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