En Python, ¿cómo itero sobre un diccionario en orden de claves ordenadas?

Hay una función existente que termina en lo siguiente, donde d es un diccionario:

 return d.iteritems() 

que devuelve un iterador sin clasificar para un diccionario dado. Me gustaría devolver un iterador que repasa los elementos ordenados por clave . ¿Cómo puedo hacer eso?

No lo he probado mucho, 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 aún funcionará 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) >>> 

Con Python 3.x, use d.items() lugar de d.iteritems() para devolver un iterador.

Utilice la función sorted() :

 return sorted(dict.iteritems()) 

Si desea un iterador real sobre los resultados ordenados, ya que sorted() devuelve una lista, use:

 return iter(sorted(dict.iteritems())) 

Las claves de un dict se almacenan en una tabla hash, de modo que es su “orden natural”, es decir, psuedo-random. Cualquier otro pedido es un concepto del consumidor del dictado.

ordenado () 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 puede usar en un bucle de una manera muy parecida a un dict, ¡pero no es de ninguna manera 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 desempaquetan 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] 

La respuesta de Greg es correcta. Ten en cuenta que en Python 3.0 tendrás que hacer

 sorted(dict.items()) 

Como los iteritems habrán desaparecido.

Ahora también puedes usar OrderedDict en Python 2.7:

 >>> 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 OrderedDict .

En general, uno puede ordenar un dict como:

 for k in sorted(d): print k, d[k] 

Para el caso específico de la pregunta, después de haber “reemplazado” 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 así la línea final cambia de

 return dict.iteritems() 

a

 return sortdict(dict) 

o

 return sortdict(dict, reverse = True) 
 >>> 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 aún tiene una clasificación O (N log N), sin embargo, después de una breve heapificación lineal, genera los elementos en orden ordenados, por lo que es teóricamente más eficiente cuando no siempre necesita la lista completa.

ordenado devuelve una lista, de ahí su error cuando intenta iterar sobre ella, pero debido a que no puede ordenar un dictado, tendrá que lidiar con una lista.

No tengo idea de cuál es el contexto más amplio de su código, pero podría intentar agregar un iterador a la lista resultante. ¿Tal vez esto ?:

 return iter(sorted(dict.iteritems())) 

Por supuesto, ahora volverá a recibir las tuplas porque las clasificó y las convirtió en una lista

ej: diga que su dictado fue: {'a':1,'c':3,'b':2} ordenado lo convierte en una lista:

 [('a',1),('b',2),('c',3)] 

por lo tanto, cuando en realidad recorres la lista, recuperas (en este ejemplo) una tupla compuesta por una cadena y un entero, pero al menos podrás iterar sobre ella.

Si desea ordenar por el orden en que se insertaron los elementos en lugar del orden de las claves, debería echar un vistazo a las colecciones de Python. OrderedDict . (Python 3 solamente)

Suponiendo que está utilizando CPython 2.x y tiene un mydict de diccionario grande, entonces el uso ordenado (mydict) va a ser lento porque ordenado genera una lista ordenada de las claves de mydict.

En ese caso, es posible que desee consultar mi paquete ordenado que incluye una implementación de C del orden sorteddict en C. Especialmente si tiene que revisar la lista ordenada de claves varias veces en diferentes etapas (es decir, cantidad de elementos) de la vida útil de los diccionarios .

http://anthon.home.xs4all.nl/Python/ordereddict/