tuplas - En Python, ¿cómo iterar sobre un diccionario en orden ordenado?
recorrer diccionario python (10)
Ahora puede usar OrderedDict
en Python 2.7 también:
>>> from collections import OrderedDict
>>> d = OrderedDict([(''first'', 1),
... (''second'', 2),
... (''third'', 3)])
>>> d.items()
[(''first'', 1), (''second'', 2), (''third'', 3)]
Aquí tienes la página de novedades para la versión 2.7 y la API de OrderedDict .
Hay una función existente que termina en:
return dict.iteritems()
que devuelve un iterador sin clasificar para un diccionario determinado. Me gustaría devolver un iterador que revise los elementos en orden ordenado. ¿Cómo puedo hacer eso?
En general, uno puede ordenar un dict como sigue:
for k in sorted(d):
print k, d[k]
Para el caso específico en la pregunta, tener un "drop in replacement" para d.iteritems (), agregue una función como:
def sortdict(d, **opts):
# **opts so any currently supported sorted() options can be passed
for k in sorted(d, **opts):
yield k, d[k]
y entonces la línea final cambia de
return dict.iteritems()
a
return sortdict(dict)
o
return sortdict(dict, reverse = True)
La respuesta de Greg es correcta. Tenga en cuenta que en Python 3.0 tendrá que hacer
sorted(dict.items())
ya que iteritems
se habrá ido.
Las claves de un dict se almacenan en una tabla hash, de modo que ese es su ''orden natural'', es decir, psuedo-aleatorio. Cualquier otro pedido es un concepto del consumidor del dict.
sorted () siempre devuelve una lista, no un dict. Si le pasa un dict.items () (que produce una lista de tuplas), devolverá una lista de tuplas [(k1, v1), (k2, v2), ...] que se pueden usar en un bucle de una manera muy parecida a un dict, ¡pero de todos modos no es un dict !
foo = {
''a'': 1,
''b'': 2,
''c'': 3,
}
print foo
>>> {''a'': 1, ''c'': 3, ''b'': 2}
print foo.items()
>>> [(''a'', 1), (''c'', 3), (''b'', 2)]
print sorted(foo.items())
>>> [(''a'', 1), (''b'', 2), (''c'', 3)]
Lo siguiente se siente como un dict en un bucle, pero no lo es, es una lista de tuplas que se desempaqueta en k, v:
for k,v in sorted(foo.items()):
print k, v
Aproximadamente equivalente a:
for k in sorted(foo.keys()):
print k, foo[k]
No lo he probado exhaustivamente, pero funciona en Python 2.5.2.
>>> d = {"x":2, "h":15, "a":2222}
>>> it = iter(sorted(d.iteritems()))
>>> it.next()
(''a'', 2222)
>>> it.next()
(''h'', 15)
>>> it.next()
(''x'', 2)
>>>
Si está acostumbrado a hacer for key, value in d.iteritems(): ...
lugar de iteradores, esto seguirá funcionando con la solución anterior
>>> d = {"x":2, "h":15, "a":2222}
>>> for key, value in sorted(d.iteritems()):
>>> print(key, value)
(''a'', 2222)
(''h'', 15)
(''x'', 2)
>>>
Si desea ordenar por el orden en que se insertaron los elementos en lugar del orden de las teclas, debe echarle un vistazo a las collections.OrderedDict de collections.OrderedDict . (Python 3 solamente)
Suponiendo que está utilizando CPython 2.x y tiene un diccionario grande mydict, entonces usar sorted (mydict) va a ser lento porque sorted crea una lista ordenada de las claves de mydict.
En ese caso, es posible que desee consultar mi paquete de orden, que incluye una implementación en C de sorteddict
en C. Especialmente si tiene que revisar la lista ordenada de claves varias veces en diferentes etapas (es decir, número de elementos) de los diccionarios de por vida .
Use la función sorted()
:
return sorted(dict.iteritems())
Si desea un iterador real sobre los resultados ordenados, dado que sorted()
devuelve una lista, use:
return iter(sorted(dict.iteritems()))
sorted devuelve una lista, de ahí su error cuando intenta iterar sobre ella, pero como no puede ordenar una dict tendrá que lidiar con una lista.
No tengo idea de cuál es el contexto más amplio de tu código, pero podrías intentar agregar un iterador a la lista resultante. ¿así quizás ?:
return iter(sorted(dict.iteritems()))
por supuesto, ahora recuperarás tuplas porque ordenó convertir tu dict en una lista de tuplas
ej .: dices que tu dict era: {''a'':1,''c'':3,''b'':2}
ordenado lo convierte en una lista:
[(''a'',1),(''b'',2),(''c'',3)]
así que cuando realmente iteras sobre la lista obtienes (en este ejemplo) una tupla compuesta de una cadena y un entero, pero al menos podrás iterar sobre ella.
>>> import heapq
>>> d = {"c": 2, "b": 9, "a": 4, "d": 8}
>>> def iter_sorted(d):
keys = list(d)
heapq.heapify(keys) # Transforms to heap in O(N) time
while keys:
k = heapq.heappop(keys) # takes O(log n) time
yield (k, d[k])
>>> i = iter_sorted(d)
>>> for x in i:
print x
(''a'', 4)
(''b'', 9)
(''c'', 2)
(''d'', 8)
Este método todavía tiene un orden O (N log N), sin embargo, después de un breve heapify lineal, produce los elementos en orden ordenado a medida que avanza, haciéndolo teóricamente más eficiente cuando no siempre se necesita toda la lista.