web-dev-qa-db-fra.com

Dictionnaires: comment garder les clés/valeurs dans le même ordre que déclaré?

J'ai un dictionnaire que j'ai déclaré dans un ordre particulier et que je veux garder dans cet ordre tout le temps. Les clés/valeurs ne peuvent pas vraiment être conservées dans l'ordre en fonction de leur valeur, je le veux juste dans l'ordre dans lequel je l'ai déclaré.

Donc si j'ai le dictionnaire:

d = {'ac': 33, 'gw': 20, 'ap': 102, 'za': 321, 'bs': 10}

Ce n'est pas dans cet ordre si je le regarde ou que je le parcours, est-il possible de s'assurer que Python conservera l'ordre explicite dans lequel j'ai déclaré les clés/valeurs?

246
roflwaffle
from collections import OrderedDict
OrderedDict((Word, True) for Word in words)

contient 

OrderedDict([('He', True), ('will', True), ('be', True), ('the', True), ('winner', True)])

Si les valeurs sont True (ou tout autre objet immuable), vous pouvez également utiliser:

OrderedDict.fromkeys(words, True)
159
eumiro

Plutôt que d’expliquer la partie théorique, je vais donner un exemple simple.

>>> from collections import OrderedDict
>>> my_dictionary=OrderedDict()
>>> my_dictionary['foo']=3
>>> my_dictionary['aol']=1
>>> my_dictionary
OrderedDict([('foo', 3), ('aol', 1)])
>>> dict(my_dictionary)
{'foo': 3, 'aol': 1}
151
Mohit Dabas

À partir de Python 3.6, le type dict standard conserve l'ordre d'insertion par défaut.

Définissant

d = {'ac':33, 'gw':20, 'ap':102, 'za':321, 'bs':10}

aboutira à un dictionnaire avec les clés dans l’ordre indiqué dans le code source.

Ceci a été réalisé en utilisant un tableau simple avec des entiers pour la table de hachage fragmentée, où ces entiers indexent dans un autre tableau qui stocke les paires clé-valeur (plus le hachage calculé). Il se trouve que ce dernier tableau stocke les éléments dans l’ordre d’insertion et que la combinaison utilise en réalité moins de mémoire que l’implémentation utilisée dans Python 3.5 et versions antérieures. Voir le idée originale de Raymond Hettinger pour plus de détails.

En 3.6, cela était encore considéré comme un détail de mise en œuvre; voir la Nouveautés de Python 3.6 documentation :

L'aspect préservant l'ordre de cette nouvelle implémentation est considéré comme un détail d'implémentation et ne doit pas être invoqué (cela peut changer dans le futur, mais nous souhaitons avoir cette nouvelle implémentation dict dans le langage pour quelques versions avant de changer les spécifications de langage. pour imposer une sémantique préservant l'ordre dans toutes les implémentations actuelles et futures de Python, cela aide également à préserver la compatibilité avec les versions antérieures du langage où l'ordre d'itération aléatoire est toujours actif (par exemple, Python 3.5).

Python 3.7 élève ce détail d'implémentation en un spécification de langage, il est donc maintenant obligatoire que dict conserve l'ordre dans toutes les implémentations Python compatibles avec cette version ou plus récente. Voir la déclaration du BDFL .

Vous souhaiterez peut-être quand même utiliser la classe collections.OrderedDict() dans certains cas, car elle offre certaines fonctionnalités supplémentaires par rapport au type dict standard. Tels que réversible (cela s'étend aux objets de vue ) et à la réorganisation (via la méthode move_to_end() ).

129
Martijn Pieters

Notez que cette réponse s'applique aux versions de python antérieures à python3.7. CPython 3.6 conserve l'ordre d'insertion dans la plupart des cas en tant que détail d'implémentation. À partir de Python3.7, il a été déclaré que les implémentations DOIVENT maintenir l'ordre d'insertion conforme.


les dictionnaires python ne sont pas ordonnés. Si vous voulez un dictionnaire commandé, essayez collections.OrderedDict .

Notez que OrderedDict a été introduit dans la bibliothèque standard en python 2.7. Si vous avez une version antérieure de Python, vous pouvez trouver des recettes pour les dictionnaires ordonnés sur ActiveState .

29
mgilson

Les dictionnaires utiliseront un ordre qui rend la recherche efficace, et vous ne pouvez rien y changer.

Vous pouvez simplement utiliser une liste d'objets (un tuple à 2 éléments dans un cas simple, voire une classe) et ajouter des éléments à la fin. Vous pouvez ensuite utiliser la recherche linéaire pour y trouver des éléments.

Vous pouvez également créer ou utiliser une structure de données différente créée dans le but de maintenir l'ordre.

12
Fire Lancer

Je suis tombé sur ce post en essayant de comprendre comment faire fonctionner OrderedDict. PyDev pour Eclipse ne pouvant pas trouver OrderedDict, j'ai donc décidé de créer un tuple des valeurs clés de mon dictionnaire, car je souhaiterais qu'elles soient commandées. Lorsque je devais sortir ma liste, je parcourais simplement les valeurs du tuple et je branchais la clé «itérée» du tuple dans le dictionnaire pour récupérer mes valeurs dans l'ordre dans lequel j'en avais besoin.

exemple:

test_dict = dict( val1 = "hi", val2 = "bye", val3 = "huh?", val4 = "what....")
test_Tuple = ( 'val1', 'val2', 'val3', 'val4')
for key in test_Tuple: print(test_dict[key])

C'est un peu lourd, mais je suis pressé et c'est la solution que j'ai trouvée.

remarque: l'approche des listes de listes suggérée par quelqu'un d'autre n'a pas vraiment de sens pour moi, car les listes sont ordonnées et indexées (et ont également une structure différente de celle des dictionnaires).

8
smushface

Vous ne pouvez pas vraiment faire ce que vous voulez avec un dictionnaire. Vous avez déjà le dictionnaire d = {'ac':33, 'gw':20, 'ap':102, 'za':321, 'bs':10}created. J'ai trouvé qu'il n'y avait aucun moyen de rester en ordre une fois qu'il est déjà créé. Ce que j'ai fait était de créer un fichier JSON à la place de l'objet:

{"ac":33,"gw":20,"ap":102,"za":321,"bs":10}

J'ai utilisé:

r = json.load(open('file.json'), object_pairs_hook=OrderedDict)

ensuite utilisé:

print json.dumps(r)

vérifier.

6
nealous3

si vous souhaitez avoir un dictionnaire dans un ordre spécifique, vous pouvez également créer une liste de listes, où le premier élément sera la clé et le second élément sera la valeur et ressemblera à ceci Exemple 

>>> list =[[1,2],[2,3]]
>>> for i in list:
...     print i[0]
...     print i[1]

1
2
2
3
2
pelos

J'ai eu un problème similaire lors du développement d'un projet Django. Je ne pouvais pas utiliser OrderedDict, car j'utilisais une ancienne version de python. La solution simple était donc d'utiliser la classe SortedDict de Django:

https://code.djangoproject.com/wiki/SortedDict

2
Evan

Généralement, vous pouvez concevoir une classe qui se comporte comme un dictionnaire, en implémentant principalement les méthodes __contains__, __getitem__, __delitem__, __setitem__ et quelques autres. Le comportement de cette classe peut être celui que vous préférez, par exemple, en plaçant un itérateur trié sur les clés ...

2
Rasmus Kaj
from collections import OrderedDict
list1 = ['k1', 'k2']
list2 = ['v1', 'v2']
new_ordered_dict = OrderedDict(Zip(list1, list2))
print new_ordered_dict
# OrderedDict([('k1', 'v1'), ('k2', 'v2')])
1
user11502624

Vous pouvez faire la même chose que j'ai fait pour le dictionnaire.

Créer une liste et un dictionnaire vide:

dictionary_items = {}
fields = [['Name', 'Himanshu Kanojiya'], ['email id', '[email protected]']]
l = fields[0][0]
m = fields[0][1]
n = fields[1][0]
q = fields[1][1]
dictionary_items[l] = m
dictionary_items[n] = q
print dictionary_items
0
Himanshu Kanojiya

Une autre alternative est d’utiliser Pandas dataframe car cela garantit l’ordre et l’emplacement des index dans une structure de type dict.

0
Ville