python - ordereddict to json
Python OrderedDict iteraciĆ³n (3)
¿Por qué mi Python OrderedDict se inicializa "fuera de servicio"?
La solución aquí es menos intrigante que la explicación. Hay algo aquí que simplemente no entiendo, y tal vez una expansión ayudaría a otros tan bien como a mí.
>>> from collections import OrderedDict
>>> spam = OrderedDict(s = (1, 2), p = (3, 4), a = (5, 6), m = (7, 8))
>>> spam
OrderedDict([(''a'', (5, 6)), (''p'', (3, 4)), (''s'', (1, 2)), (''m'', (7, 8))])
>>> for key in spam.keys():
... print key
...
# this is ''ordered'' but not the order I wanted....
a
p
s
m
# I was expecting (and wanting):
s
p
a
m
@Chris Krycho dio una buena explicación de por qué las cosas fallan.
Si observa el repr () de un OrderedDict, obtendrá una pista sobre cómo impartir el orden desde el principio: debe usar una lista de pares (clave, valor) para conservar el orden de las claves que se indican en la lista.
Aquí hay uno que hice antes:
>>> from collections import OrderedDict
>>> spamher = OrderedDict(s=6, p=5, a=4, m=3, h=2, e=1, r=0)
>>> spamher
OrderedDict([(''h'', 2), (''m'', 3), (''r'', 0), (''s'', 6), (''p'', 5), (''a'', 4), (''e'', 1)])
>>>
>>> list(spamher.keys())
[''h'', ''m'', ''r'', ''s'', ''p'', ''a'', ''e'']
>>>
>>> spamher = OrderedDict([(''s'', 6), (''p'', 5), (''a'', 4), (''m'', 3), (''h'', 2), (''e'', 1), (''r'', 0)])
>>> list(spamher.keys())
[''s'', ''p'', ''a'', ''m'', ''h'', ''e'', ''r'']
>>>
(Dio la casualidad de que en Python v3.3.0, su ejemplo original de spam
mantuvo las claves en su orden original desde el principio. Cambié a spamher
para conocer esto).
Como las other answers han mencionado, tratar de pasar un dictado a OrderedDict o usar argumentos de palabras clave no conserva el orden. Sin embargo, pasar en tuplas es un poco feo, y esto es Python. Debe ser hermoso
Puede usar __getitem__
en una clase para tener una sintaxis similar a dict para crear "literales" de OrderedDict:
from collections import OrderedDict
class OD(object):
"""This class provides a nice way to create OrderedDict "literals"."""
def __getitem__(self, slices):
if not isinstance(slices, tuple):
slices = slices,
return OrderedDict((slice.start, slice.stop) for slice in slices)
# Create a single instance; we don''t ever need to refer to the class.
OD = OD()
Ahora puedes usar una sintaxis similar a dict para crear un OrderedDict:
spam = OD[''s'': (1, 2),
''p'': (3, 4),
''a'': (5, 6),
''m'': (7, 8)]
assert(''''.join(spam.keys()) == ''spam'')
Esto funciona porque dentro de los corchetes, Python crea literales de slice , que se parecen a la sintaxis dict si escudriñas un poco.
La clase OD
podría beneficiarse de la verificación de errores, pero esto demuestra cómo puede funcionar.
De la documentación :
El constructor OrderedDict y el método
update()
aceptan argumentos de palabras clave, pero su orden se pierde porque la función de Python llama a la semántica y pasa los argumentos de palabras clave que usan un diccionario normal no ordenado.
Así que la inicialización pierde el ordenamiento, porque básicamente está llamando a un constructor con **kwargs
.
Edición: en términos de una solución (no solo una explicación ), como se señaló en un comentario del OP , pasar una única lista de tuplas funcionará:
>>> from collections import OrderedDict
>>> spam = OrderedDict([(''s'',(1,2)),(''p'',(3,4)),(''a'',(5,6)),(''m'',(7,8))])
>>> for key in spam:
... print(key)
...
s
p
a
m
>>> for key in spam.keys():
... print(key)
...
s
p
a
m
Esto se debe a que solo se obtiene un único argumento, una lista.