A ordem das chaves nos dicionários

101

Código:

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

print l

Isso imprime ['a', 'c', 'b']. Não tenho certeza de como o método keys()determina a ordem das palavras-chave em l . No entanto, gostaria de poder recuperar as palavras-chave na ordem "adequada". A ordem correta, claro, criaria a lista ['a', 'b', 'c'].

retângulo
fonte
3
Se os dicionários Python são como a maioria, eles são, na verdade, tabelas de hash. Entre outras coisas, isso significa que a ordem das chaves não é garantida ou mesmo especificada. Em particular, ele não lembraria a ordem em que as chaves são adicionadas.
cHao
3
@cHao: Isso significa essencialmente que seu programa será indeterminista se você repetir os elementos de um dicionário?
HelloGoodbye
4
@HelloGoodbye: Eu não iria tão longe; ainda há um comportamento muito previsível lá. Cada iteração completa vê exatamente um de cada par chave / valor. E, na maioria dos idiomas, você os verá sempre na mesma ordem. A menos que os documentos garantam um pedido específico, no entanto, você não deve esperar que seja o pedido que deseja. (Algumas linguagens (como Perl) irão na verdade randomizar um pouco a ordem - supostamente por razões de segurança, mas eu acho que é apenas para sacudir você do hábito de confiar em um comportamento não especificado. :) Não acho que Python seja bem assim aquele mal, mas eh ...)
cHao
1
O pedido será o mesmo, desde que o dicionário não tenha sido modificado. Do manual: "Se itens (), chaves (), valores (), iteritems (), iterkeys () e itervalues ​​() forem chamados sem modificações no dicionário, as listas corresponderão diretamente. Isso permite a criação de (valor, chave) pares usando zip (): pares = zip (d.values ​​(), d.keys ()). "
steveayre
2
@sfranky Acho que o que steveayre quis dizer é que a ordem é a mesma entre o que você obtém usando os diferentes métodos mencionados, não a mesma que a ordem em que os elementos foram escritos.
bli

Respostas:

78

Você pode usar OrderedDict (requer Python 2.7) ou superior.

Além disso, observe que OrderedDict({'a': 1, 'b':2, 'c':3})isso não funcionará, pois o que dictvocê cria com {...}já esqueceu a ordem dos elementos. Em vez disso, você deseja usarOrderedDict([('a', 1), ('b', 2), ('c', 3)]) .

Conforme mencionado na documentação, para versões anteriores ao Python 2.7, você pode usar esta receita.

Abhinav Gupta
fonte
18
Lembre-se de que a ordem de um OrderedDict é o pedido de inserção ; as chaves só sairão em ordem alfabética se você as inserir dessa forma.
Hugh Bothwell
é o que ele mostrou como um exemplo simplificado; pode ou não ter qualquer relação com como ele realmente planeja usá-lo. Já encontrei pessoas que esperavam que OrderedDict retornasse inserções arbitrárias em ordem classificada, então achei que deveria apontar isso.
Hugh Bothwell,
119

Python 3.7+

No Python 3.7.0, a natureza de preservação da ordem de inserção dos dictobjetos foi declarada como uma parte oficial das especificações da linguagem Python. Portanto, você pode contar com isso.

Python 3.6 (CPython)

A partir do Python 3.6, para a implementação CPython do Python, os dicionários mantêm a ordem de inserção por padrão. No entanto, isso é considerado um detalhe de implementação; você ainda deve usar collections.OrderedDictse quiser uma ordem de inserção garantida em outras implementações do Python.

Python> = 2.7 e <3.6

Use a collections.OrderedDictclasse quando precisar de um dictque lembre a ordem dos itens inseridos.

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

Use a função classificada , que classifica o iterável passado.

O .keys()método retorna as chaves em uma ordem arbitrária.

Mike Lewis
fonte
12
Isso não funciona se você quiser o pedido original e ele não foi classificado.
Simon
12

Basta classificar a lista quando quiser usá-la.

l = sorted(d.keys())
Desenhou
fonte
1

Embora a ordem não importe, pois o dicionário é um hashmap. Depende da ordem em que é inserido:

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()))

saída:
para string abbc, as chaves são dict_keys (['a', 'b', 'c'])
para string cbab, as chaves são dict_keys (['c', 'b', 'a'])

Zehai
fonte
1
Dicionário em python são inseridos pedidos apenas a partir da versão 3.6+ verifique isto
Crivella