2008-09-13 22 views

Respuesta

49

La python estándar dict no puede hacer esto.

Hay una propuesta (PEP 372) para agregar un "diccionario ordenado" (que realiza un seguimiento del orden de inserción) al módulo collections en la biblioteca estándar. Incluye enlaces a variousimplementationsofordereddictionaries (vea también estos tworecipes en el Cookbook de Python).

Es posible que desee seguir con la implementación de referencia en el PEP si desea que su código sea compatible con la versión "oficial" (si finalmente se acepta la propuesta).

EDITAR: El PEP fue aceptado y agregado en python 2.7 y 3.1. Ver the docs.

6

No se puede hacer esto con la clase base dict - se ordena con hash. Puede construir su propio diccionario que sea realmente una lista de pares clave, de valor o somesuch, que se ordenarían.

+2

La implementación del diccionario puede utilizar un diccionario estándar y una lista, el diccionario almacena la clave-> valor asociaciones, y la lista almacena claves en el orden en que y están insertados. –

18

Las otras respuestas son correctas; no es posible, pero podrías escribir esto tú mismo. Sin embargo, en caso de que no esté seguro de cómo implementar realmente algo como esto, aquí hay una implementación completa y funcional que subclasifica el dict que acabo de escribir y probar. (Tenga en cuenta que el orden de los valores pasados ​​al constructor no está definido, pero vendrá antes de valores pasados ​​más tarde, y siempre se puede simplemente no permite predice la orden de ser inicializado con los valores.)

class ordered_dict(dict): 
    def __init__(self, *args, **kwargs): 
     dict.__init__(self, *args, **kwargs) 
     self._order = self.keys() 

    def __setitem__(self, key, value): 
     dict.__setitem__(self, key, value) 
     if key in self._order: 
      self._order.remove(key) 
     self._order.append(key) 

    def __delitem__(self, key): 
     dict.__delitem__(self, key) 
     self._order.remove(key) 

    def order(self): 
     return self._order[:] 

    def ordered_items(self): 
     return [(key,self[key]) for key in self._order] 


od = ordered_dict() 
od["hello"] = "world" 
od["goodbye"] = "cruel world" 
print od.order()   # prints ['hello', 'goodbye'] 

del od["hello"] 
od["monty"] = "python" 
print od.order()   # prints ['goodbye', 'monty'] 

od["hello"] = "kitty" 
print od.order()   # prints ['goodbye', 'monty', 'hello'] 

print od.ordered_items() 
# prints [('goodbye','cruel world'), ('monty','python'), ('hello','kitty')] 
+0

¿Ordene correctamente order_dict (('key_a', 'value_a'), ('key_b', 'value_b'))? Parece que el orden se establecerá en self.keys() en __init__, que se ordena en el orden de hash, no en el orden en que se ingresó? Sólo curioso. –

+0

Está en lo correcto, por lo que dije: "el orden de los valores pasados ​​al constructor no está definido, pero vendrá antes de que los valores pasen luego". Sería posible ordenarlos adecuadamente, pero no estaba seguro de si ese era un comportamiento deseado, ya que podría decirse que dichos objetos se insertan simultáneamente. –

0

si no es necesario la funcionalidad dict, y solo necesita devolver tuplas en el orden en que las insertó, ¿no funcionaría mejor una cola?

7

O, simplemente, hacer que la llave con una tupla time.now() como el primer campo de la tupla.

Luego puede recuperar las claves con dictname.keys(), sort y ¡voila!

Gerry

+1

Esto hace que sea imposible buscar entradas en el diccionario sin saber exactamente cuándo las insertó. No es mejor que una lista de pares clave-valor. – user2357112

1

No es posible a menos que almacenar las claves en una lista separada para hacer referencia más adelante.

2

O utilice cualquiera de las implementaciones para el PEP-372 descrito here, como el odict module del pythonutils.

He utilizado con éxito el pocoo.aplicación org, es tan fácil como la sustitución de su

my_dict={} 
my_dict["foo"]="bar" 

con

my_dict=odict.odict() 
my_dict["foo"]="bar" 

y requieren solo this file

1

Lo que puede hacer es insertar los valores con una clave que representa la orden introducida, y luego llame al sorted() en los artículos.

>>> obj = {} 
>>> obj[1] = 'Bob' 
>>> obj[2] = 'Sally' 
>>> obj[3] = 'Joe' 
>>> for k, v in sorted(obj.items()): 
...  print v 
... 
Bob 
Sally 
Joe 
>>> 
+1

Si no necesitáramos la clave para otros fines, usaríamos una lista. Esto no hace nada, una lista no funciona mejor. – user2357112

+1

@ user2357112, sin embargo, esto expresa otro método de hacer ** lo que pidió el OP **. El OP no preguntó cómo imprimir los artículos en el orden en que se insertaron, el OP dijo cómo imprimir los artículos ** en un 'dict' **. Gran diferencia. –

+0

Has cambiado el formato de la dicción hasta el punto de hacerla inútil para el propósito original. Si originalmente el dict estaba asociando, por ejemplo, nombres a números de teléfono, ha ganado un orden de iteración constante, pero no tiene idea de cuál es el número de teléfono de Bob. – user2357112

6

Uso OrderedDict(), disponible desde la versión 2.7

Sólo es cuestión de curiosidad:

from collections import OrderedDict 
a = {} 
b = OrderedDict() 
c = OredredDict() 

a['key1'] = 'value1' 
a['key2'] = 'value2' 

b['key1'] = 'value1' 
b['key2'] = 'value2' 

c['key2'] = 'value2' 
c['key1'] = 'value1' 

print a == b #True 
print a == C#True 
print b == C#False 
Cuestiones relacionadas