El orden de las claves en los diccionarios

101

Código:

d = {'a': 0, 'b': 1, 'c': 2}
l = d.keys()

print l

Esto imprime ['a', 'c', 'b']. No estoy seguro de cómo el método keys()determina el orden de las palabras clave dentro de l . Sin embargo, me gustaría poder recuperar las palabras clave en el orden "adecuado". Por supuesto, el orden correcto crearía la lista ['a', 'b', 'c'].

rectángulo
fuente
3
Si los diccionarios de Python son como la mayoría, en realidad son tablas hash. Entre otras cosas, eso significa que el orden de las claves no está garantizado ni siquiera especificado. En particular, no recordaría el orden en que se agregan las claves.
cHao
3
@cHao: ¿Esto esencialmente significa que su programa será indeterminista si recorre los elementos en un diccionario?
Hola
4
@HelloGoodbye: Yo no iría tan lejos; todavía hay un comportamiento muy predecible allí. Cada iteración completa ve exactamente uno de cada par clave / valor. Y en la mayoría de los idiomas, incluso los verá en el mismo orden cada vez. Sin embargo, a menos que los documentos garanticen un pedido en particular, no debe contar con que sea el pedido que desea. (Algunos lenguajes (como Perl) en realidad aleatorizarán un poco el orden, supuestamente por razones de seguridad, pero creo que en realidad es solo para liberarte del hábito de depender de un comportamiento no especificado. :) No creo que Python sea tan ese mal, pero eh ...)
cHao
1
El orden será el mismo siempre que no se haya modificado el dictado. Del manual: "Si se llama a items (), keys (), values ​​(), iteritems (), iterkeys () e itervalues ​​() sin modificaciones al diccionario, las listas se corresponderán directamente. Esto permite la creación de pares (valor, clave) usando zip (): pares = zip (d.values ​​(), d.keys ()). "
steveayre
2
@sfranky Creo que lo que steveayre quiso decir es que el orden es el mismo entre lo que obtienes usando los diferentes métodos mencionados, no el mismo que el orden en el que se escribieron los elementos.
bli

Respuestas:

78

Puede usar OrderedDict (requiere Python 2.7) o superior.

Además, tenga en cuenta que OrderedDict({'a': 1, 'b':2, 'c':3})no funcionará ya que el dictque crea con {...}ya ha olvidado el orden de los elementos. En su lugar, desea utilizar OrderedDict([('a', 1), ('b', 2), ('c', 3)]).

Como se menciona en la documentación, para versiones anteriores a Python 2.7, puede usar esta receta.

Abhinav Gupta
fuente
18
Tenga en cuenta que el orden de un OrderedDict es el orden de inserción ; las claves solo aparecerán en orden alfabético si las inserta de esa manera.
Hugh Bothwell
es lo que mostró como un ejemplo simplificado; puede tener o no relación con cómo planea usarlo. Anteriormente me he encontrado con personas que esperaban que OrderedDict devolviera inserciones arbitrarias en orden ordenado, por lo que sentí que debería señalar esto.
Hugh Bothwell
119

Python 3.7+

En Python 3.7.0, la naturaleza de conservación del orden de inserción de los dictobjetos ha sido declarada como una parte oficial de la especificación del lenguaje Python. Por lo tanto, puede confiar en ello.

Python 3.6 (CPython)

A partir de Python 3.6, para la implementación CPython de Python, los diccionarios mantienen el orden de inserción de forma predeterminada. Sin embargo, esto se considera un detalle de implementación; aún debe usarlo collections.OrderedDictsi desea un orden de inserción que esté garantizado en otras implementaciones de Python.

Python> = 2.7 y <3.6

Utilice la collections.OrderedDictclase cuando necesite una dictque recuerde el orden de los elementos insertados.

Eugene Yarmash
fuente
48
>>> print sorted(d.keys())
['a', 'b', 'c']

Utilice la función ordenada , que ordena el iterable pasado.

El .keys()método devuelve las claves en un orden arbitrario.

Mike Lewis
fuente
12
Esto no funciona si desea el pedido original y no fue ordenado.
Simon
12

Solo ordena la lista cuando quieras usarla.

l = sorted(d.keys())
Dibujó
fuente
1

Aunque el orden no importa ya que el diccionario es hashmap. Depende del orden en que se inserte:

s = 'abbc'
a = 'cbab'

def load_dict(s):
    dict_tmp = {}
    for ch in s:
        if ch in dict_tmp.keys():
            dict_tmp[ch]+=1
        else:
            dict_tmp[ch] = 1
    return dict_tmp

dict_a = load_dict(a)
dict_s = load_dict(s)
print('for string %s, the keys are %s'%(s, dict_s.keys()))
print('for string %s, the keys are %s'%(a, dict_a.keys()))

salida:
para la cadena abbc, las claves son dict_keys (['a', 'b', 'c'])
para la cadena cbab, las claves son dict_keys (['c', 'b', 'a'])

zehai
fuente
1
El diccionario en python se ordena por inserción solo a partir de la versión 3.6+ verifique esto
Crivella