Conversion de dict en OrderedDict

138

J'ai du mal à utiliser la collections.OrderedDictclasse. J'utilise Python 2.7 sur Raspbian, la distribution Debian pour Raspberry Pi. J'essaie d'imprimer deux dictionnaires afin de les comparer (côte à côte) pour une aventure textuelle. La commande est essentielle pour comparer avec précision. Peu importe ce que j'essaye, les dictionnaires s'impriment de leur manière non ordonnée habituelle.

Voici ce que j'obtiens quand 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)])

De toute évidence, il y a 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 ...

Voici 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 dans l'ordre, mais il ne devrait pas imprimer les autres choses, n'est-ce pas? (La mise en liste et l'affichage de l'appel de fonction.)

Où est-ce que je fais mon erreur? Cela ne devrait rien avoir à voir avec la version pi de Python car ce n'est que la version Linux.

pythonpiboy
la source
3
Remarque: OrderedDictest trié par ordre d'insertion et non par ordre de touches alphanumériques.
el.pescado

Réponses:

214

Vous créez un dictionnaire d' abord , en faisant passer ce dictionnaire à un OrderedDict. Pour les versions Python <3.6 (*) , au moment où vous faites cela, l'ordre ne sera plus correct. dictn'est pas ordonné par nature.

Passez plutôt une séquence de tuples:

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

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


(*) : Dans l'implémentation CPython 3.6, le dicttype a été mis à jour pour utiliser une structure interne plus efficace en 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èmes. Depuis Python 3.7, la spécification du langage Python a été mise à jour pour exiger que toutes les implémentations Python doivent suivre ce comportement. Voir cette autre réponse pour plus de détails et aussi pourquoi vous voudrez peut-être toujours utiliser un OrderedDict()dans certains cas.

Martijn Pieters
la source
Ok, donc OrderedDict créera le dictionnaire pour moi? De plus, pour imprimer sans la représentation reproductible, puis-je simplement imprimer la variable dans laquelle OrderedDict est utilisé? c'est-à-dire: print ship ?? Merci :)
pythonpiboy
3
Question: Comme vous l'avez décrit, OrderedDict crée une "liste" ordonnée. Cela ne va-t-il pas à l'encontre du but? Il crée juste une liste d'éléments, pas de dictionnaires avec des clés et des valeurs ...
pythonpiboy
9
Le type agit comme les deux; une cartographie qui conserve l'ordre. Pour en créer un avec la commande, vous devez lui donner les éléments dans l'ordre . Puisqu'un dict standard (sur autre chose que PyPI ou Python 3.6+) ne peut pas faire cela, vous lui donnez une liste de tuples à la place. Une fois que l' OrderedDicton a créé c'est un dictionnaire.
Martijn Pieters
4
On dirait que la confusion vient du fait qu'un OrderedDict "applique" un ordre, plutôt que de simplement conserver un ordre. J'ai certainement supposé que cela trierait l'entrée lors de la création - ou que la fonction items () renverrait des éléments triés indépendamment du moment où ils étaient insérés. Au lieu de cela, il conserve simplement la commande que vous fournissez.
whiterook6
2
@ whiterook6: ce n'est pas un dictionnaire trié non. C'est un dictionnaire ordonné, un dictionnaire qui enregistre l'ordre des paires clé-valeur et vous permet de réorganiser ces paires. Comparez cela aux listes, qui sont des séquences ordonnées .
Martijn Pieters
36

Si vous ne pouvez pas modifier cette partie du code où votre dict a été défini, vous pouvez toujours le commander à tout moment comme vous le souhaitez, 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)
Jan Rozycki
la source
11

La plupart du temps, nous utilisons OrderedDict lorsque nous avons besoin d'une commande personnalisée et non 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)])

Remarque : les nouveaux dictionnaires triés conservent leur ordre de tri lorsque les entrées sont supprimées. Mais lorsque de nouvelles clés sont ajoutées, les clés sont ajoutées à la fin et le tri n'est pas maintenu. ( Doc officiel )

Abdul Majeed
la source
2

Utilisez dict.items (); cela peut être aussi simple que suivant:

ship = collections.OrderedDict(ship.items())
Mohammad-Ali
la source