Maneira correta de inicializar um OrderedDict usando seu construtor para que ele retenha a ordem dos dados iniciais?


124

Qual é a maneira correta de inicializar um dicionário ordenado (OD) para manter a ordem dos dados iniciais?

from collections import OrderedDict

# Obviously wrong because regular dict loses order
d = OrderedDict({'b':2, 'a':1}) 

# An OD is represented by a list of tuples, so would this work?
d = OrderedDict([('b',2), ('a', 1)])

# What about using a list comprehension, will 'd' preserve the order of 'l'
l = ['b', 'a', 'c', 'aa']
d = OrderedDict([(i,i) for i in l])

Questão:

  • Uma OrderedDictpreserva a ordem de uma lista de tuplas, ou tupla de tuplas ou tupla de listas ou lista de listas etc., passada no momento da inicialização (segundo e terceiro exemplo acima)?

  • Como se verifica se OrderedDictrealmente mantém um pedido? Como a dictpossui uma ordem imprevisível, e se meus vetores de teste tiverem, felizmente, a mesma ordem inicial que a ordem imprevisível de um ditado? Por exemplo, se em vez de d = OrderedDict({'b':2, 'a':1})escrever d = OrderedDict({'a':1, 'b':2}), posso concluir erroneamente que a ordem está preservada. Nesse caso, descobri que a dicté ordenado alfabeticamente, mas isso nem sempre é verdade. Qual é uma maneira confiável de usar um contraexemplo para verificar se uma estrutura de dados preserva a ordem ou não, exceto por tentar vetores de teste repetidamente até que um deles se quebre?

PS: Vou deixar isso aqui apenas para referência : "O construtor OrderedDict e o método update () aceitam argumentos de palavras-chave, mas sua ordem é perdida porque a função do Python chama argumentos de palavras-passe de semântica de passagem de semântica usando um dicionário regular não ordenado"

PPS: Felizmente, no futuro, o OrderedDict também preservará a ordem dos kwargs (exemplo 1): http://bugs.python.org/issue16991


10
É vagamente irônico que inicializar um OrderedDict com um ditado (não vazio) seja a coisa errada a ser feita ... sem dúvida isso deve resultar em um Aviso, pois provavelmente viola a intenção do usuário.
SMCI

3
Depois do python3.6, OrderDict(b=2, a=1)também é uma maneira adequada. Veja PEP 468 .
IvanaGyro 10/08/19

Respostas:


90

O OrderedDict preservará qualquer pedido ao qual ele tenha acesso. A única maneira de passar dados ordenados para inicializar é passar uma lista (ou, geralmente, uma iterável) de pares de valores-chave, como nos dois últimos exemplos. Como diz a documentação à qual você vinculou, o OrderedDict não tem acesso a nenhum pedido quando você passa argumentos de palavras-chave ou dict, pois qualquer pedido é removido antes que o construtor OrderedDict o veja.

Observe que o uso de uma compreensão de lista em seu último exemplo não muda nada. Não há diferença entre OrderedDict([(i,i) for i in l])e OrderedDict([('b', 'b'), ('a', 'a'), ('c', 'c'), ('aa', 'aa')]). A compreensão da lista é avaliada e cria a lista e é transmitida; OrderedDict não sabe nada sobre como foi criado.


74
# An OD is represented by a list of tuples, so would this work?
d = OrderedDict([('b', 2), ('a', 1)])

Sim, isso vai funcionar. Por definição, uma lista é sempre ordenada da maneira como é representada. Isso vale também para a compreensão da lista, a lista gerada é da mesma maneira que os dados foram fornecidos (ou seja, a fonte de uma lista será determinística, originada de uma quantidade setou dictnão muito).

Como alguém verifica se OrderedDictrealmente mantém um pedido? Como um ditado tem uma ordem imprevisível, e se meus vetores de teste tiverem a mesma ordem inicial que a ordem imprevisível de um ditado? Por exemplo, se em vez de d = OrderedDict({'b':2, 'a':1})escrever d = OrderedDict({'a':1, 'b':2}), posso concluir erroneamente que a ordem está preservada. Nesse caso, descobri que a dicté uma ordem alfabética, mas isso nem sempre é verdade. ou seja, qual é uma maneira confiável de usar um exemplo de contador para verificar se uma estrutura de dados preserva a ordem ou não tenta os vetores de teste repetidamente até que um deles se quebre.

Você mantém sua lista de fontes com 2 tuplas para referência e as usa como dados de teste para seus casos de teste ao realizar testes de unidade. Faça uma iteração entre eles e garanta que o pedido seja mantido.


Sobre a verificação do pedido: Como garantir que minhas duas tuplas quebrarão a ordem do ditado se for imprevisível? Esta é uma pergunta genérica sobre qualquer estrutura de dados, talvez eu deva separá-la desta questão.
clique em

1
Você não pode quebrar deterministicamente algo que não é determinístico por natureza.
metatoaster 25/08/14

1
Então, qual é a abordagem correta para testar essas coisas? Você continua tentando indefinidamente? A ordem é imprevisível para os programadores, mas como é um mapa de hash, segue-se o algoritmo 'some' e um teste correto deve tentar combater isso?
clique em

2
Veja __hash__. Especificamente sobre o strtipo.
Metatoaster

Por definição, uma lista é sempre ordenada da maneira como é representada. Esta foi uma afirmação chave para mim. Decidi simplesmente usar uma lista de duas tuplas para o meu básico, OrderedDictpara que eu não tenha a sobrecarga de converter uma lista em um OrderedDict. Eu apenas percorro os elementos como uma lista em vez de um dicionário.
Bobort
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.