Eu tenho isto:
d1 = OrderedDict([('a', '1'), ('b', '2')])
Se eu fizer isso:
d1.update({'c':'3'})
Então eu entendo:
OrderedDict([('a', '1'), ('b', '2'), ('c', '3')])
mas eu quero isso:
[('c', '3'), ('a', '1'), ('b', '2')]
sem criar um novo dicionário.
python
python-3.x
dictionary
python-2.x
ordereddict
user2392209
fonte
fonte
Respostas:
Não há nenhum método integrado para fazer isso no Python 2. Se você precisar disso, deverá escrever um
prepend()
método / função que opere noOrderedDict
componentes internos com complexidade O (1).Para Python 3.2 e posterior, você deve usar o
move_to_end
método. O método aceita umlast
argumento que indica se o elemento será movido para a parte inferior (last=True
) ou superior (last=False
) doOrderedDict
.Finalmente, se você deseja uma solução rápida, suja e lenta , pode apenas criar um novo
OrderedDict
do zero.Detalhes para as quatro soluções diferentes:
Estenda
OrderedDict
e adicione um novo método de instânciaDemo:
Função autônoma que manipula
OrderedDict
objetosEsta função faz a mesma coisa aceitando o objeto, chave e valor dict. Eu pessoalmente prefiro a aula:
Demo:
Use
OrderedDict.move_to_end()
(Python> = 3.2)Python 3.2 introduziu o
OrderedDict.move_to_end()
método. Usando-o, podemos mover uma chave existente para qualquer extremidade do dicionário no tempo O (1).Se precisarmos inserir um elemento e movê-lo para o topo, tudo em uma etapa, podemos usá-lo diretamente para criar um
prepend()
wrapper (não apresentado aqui).Crie um novo
OrderedDict
- lento !!!Se você não quiser fazer isso e o desempenho não for um problema , a maneira mais fácil é criar um novo dicionário:
resultado:
fonte
c
já existir, isso não atualizará o valor antigomove_to_end
então não há tag Python 3 na questão,move_to_end
funciona apenas no Python 3.2+. Vou atualizar minha resposta para incluir a solução baseada em Python 3. Muito obrigado pela atualização!move_to_front
, talvez seja melhor implementar ummove_to_front
método em vez de umprepend
método separado ? Isso tornará seu código mais portátil se você precisar oferecer suporte a Python 2 e Python 3 a partir da mesma base de código.dict_setitem=dict.__setitem__
como paramprepend
? Por que alguém iria / deveria passar por um setter diferente?ordered_dict_prepend
acima. Chamarordered_dict_prepend(d, 'c', 100)
duas vezes e tentar imprimir o dicionário resultante (simplesmente inserindod
no console do Python) resulta no processo Python continua agarrando memória. Testado com Python 2.7.10EDIT (03/02/2019) Observe que a seguinte resposta só funciona em versões anteriores do Python. Mais recentemente,
OrderedDict
foi reescrito em C. Além disso, ele toca os atributos de sublinhado duplo que são desaprovados.Acabei de escrever uma subclasse de
OrderedDict
em um projeto meu para um propósito semelhante. Aqui está a essência .As operações de inserção também são constantes
O(1)
(não exigem que você reconstrua a estrutura de dados), ao contrário da maioria dessas soluções.fonte
TypeError: '_Link' object does not support indexing
quando uso isso no Python 3.4.OrderedDict
foi reescrito em C a partir do Python 3.5, e essa subclasse cometeu o tabu de bagunçar detalhes internos (na verdade, inverter a mutilação de nomes para acessar __ propriedades).Você tem que fazer uma nova instância de
OrderedDict
. Se suas chaves forem exclusivas:Mas se não, cuidado, pois este comportamento pode ou não ser desejado para você:
fonte
OrderedDict
instável a ordem final dos itens no resultado .Se você sabe que deseja uma tecla 'c', mas não sabe o valor, insira 'c' com um valor fictício ao criar o dict.
e altere o valor posteriormente.
fonte
Isso agora é possível com move_to_end (key, last = True)
https://docs.python.org/3/library/collections.html#collections.OrderedDict.move_to_end
fonte
FWIW Aqui está um código rápido e sujo que escrevi para inserir em uma posição de índice arbitrária. Não necessariamente eficiente, mas funciona no local.
fonte
Você pode querer usar uma estrutura totalmente diferente, mas há maneiras de fazer isso no python 2.7 .
d2 então conterá
Como mencionado por outros, no python 3.2 você pode usar
OrderedDict.move_to_end('c', last=False)
para mover uma determinada chave após a inserção.fonte
Se você precisar de uma funcionalidade que não existe, basta estender a classe com o que quiser:
Não é muito eficiente, mas funciona:
fonte
Eu sugeriria adicionar um
prepend()
método a esta receita pura do Python ActiveState ou derivar uma subclasse dele. O código para fazer isso pode ser bastante eficiente, visto que a estrutura de dados subjacente para ordenação é uma lista vinculada.Atualizar
Para provar que essa abordagem é viável, abaixo está o código que faz o que é sugerido. Como bônus, também fiz algumas pequenas alterações adicionais para começar a trabalhar no Python 2.7.15 e 3.7.1.
Um
prepend()
método foi adicionado à classe na receita e foi implementado em termos de outro método que foi adicionado chamadomove_to_end()
, que foi adicionadoOrderedDict
no Python 3.2.prepend()
também pode ser implementado diretamente, quase exatamente como mostrado no início do @Ashwini Chaudhary resposta -e isso provavelmente resultaria em ele ser um pouco mais rápido, mas que foi deixado como um exercício para o leitor motivado ...fonte
Obtive um loop infinito ao tentar imprimir ou salvar o dicionário usando @Ashwini Chaudhary answer com Python
2.7
. Mas consegui reduzir um pouco o código dele e o fiz funcionar aqui:fonte
Este é um dicionário ordenado padrão que permite inserir itens em qualquer posição e usar o. operador para criar chaves:
fonte