Existe uma maneira de excluir um item de um dicionário em Python?
Além disso, como posso excluir um item de um dicionário para retornar uma cópia (ou seja, sem modificar o original)?
python
dictionary
del
richzilla
fonte
fonte
pop
altera o dicionário no local . Portanto, altera a referência ao dicionário que foi passado do chamador para a "função auxiliar". Portanto, a "função auxiliar" não precisa retornar nada, pois a referência original ao dicionário no chamador já será alterada. Não atribua o retorno dedict.pop()
nada se você não precisar. EG:do stuff with my_dict; my_dict.pop(my_key, None); do more stuff with my_dict # now doesn't have my_key
. Usedeepcopy(my_dict)
se necessário.d.pop()
, eu o corrigi para fazer a pergunta especificada nos detalhes.d.pop(key)
. Mas se alguma coisa modificar a cópia superficial, você terá um problema conhecido com o alias . Ajuda se você nos contar o contexto mais amplo. (É qualquer outra coisa que nunca modificar os valores de dicionários Você está tentando destrutivamente iterar sobre uma lista se não, o quê???)Respostas:
A
del
instrução remove um elemento:No entanto, isso modifica o dicionário existente para que o conteúdo do dicionário seja alterado para qualquer pessoa que tenha uma referência à mesma instância. Para retornar um novo dicionário, faça uma cópia do dicionário:
O
dict()
construtor faz uma cópia superficial . Para fazer uma cópia detalhada, consulte ocopy
módulo .Note que fazer uma cópia para cada ditado
del
/ tarefa / etc. significa que você está indo do tempo constante para o tempo linear e também usando espaço linear. Para ditados pequenos, isso não é um problema. Mas se você planeja fazer muitas cópias de dictos grandes, provavelmente deseja uma estrutura de dados diferente, como um HAMT (conforme descrito nesta resposta ).fonte
dict
que estiver percorrendo, eleRuntimeError: dictionary changed size during iteration
pop
método que de fato faz o mesmo? Não é mais pitônico? (sendo o método do ditado, não uma palavra reservada especial)?pop
muda o dicionário.Se você quiser manter o original, basta copiá-lo.
fonte
pop
retorna o valor que foi 'popped', o que permite que você use esse valor por qualquer outro motivo. Se não é mais "Pythonic", eu diria que parece melhor, com certeza :). Não é um ditado, mas funciona da mesma maneira para ambos: github.com/ivanlmj/python-prototypes/blob/master/3.4/…pop
pode ser fornecido com um valor padrão que será retornado quando uma chave estiver ausente do dict. É bom quando você precisa remover algumas chaves, mas algumas delas podem estar ausentes;del
jogariaKeyError
nesse caso.Eu acho que sua solução é a melhor maneira de fazê-lo. Mas se você quiser outra solução, poderá criar um novo dicionário usando as chaves do dicionário antigo, sem incluir a chave especificada, assim:
fonte
{i:a[i] for i in a if i not in [0, 1, 2]}
se você deseja remover vários elementos.{k:v for k,v in a.items() if k != 0}
eu acho.**kwargs
,some_function(**{k:v for k,v in some_dict.items() if k not 'some_key'})
A declaração del é o que você está procurando. Se você tem um dicionário chamado foo com uma chave chamada 'bar', é possível excluir 'bar' de foo assim:
Observe que isso modifica permanentemente o dicionário que está sendo operado. Se você deseja manter o dicionário original, precisará criar uma cópia com antecedência:
A
dict
chamada faz uma cópia superficial. Se você quiser uma cópia profunda, usecopy.deepcopy
.Aqui está um método que você pode copiar e colar, para sua conveniência:
fonte
>>>
é frequentemente usado nos exemplos de python? Sim, o python-doc contém muitas dessas coisas. Mas esse código não é conveniente para copypaste . Estou confuso ...>>>
imita a notação de escuta de python no modo cli>>>
. Sim, é estilo REPL, mas vamos falar francamente: o único homem que escreveu essa amostra e 1000 leram isso. Eu acho que seria ótimo escrever exemplos da maneira que permite copiar e executar com facilidade. Não gosto de remover esses colchetes à mão. Ou copie linha por linha .. Então, eu não entendo: por que esses ângulos ainda estão lá)))) Talvez eu não saiba de algo?Há muitas respostas legais, mas quero enfatizar uma coisa.
Você pode usar o
dict.pop()
método e umadel
instrução mais genérica para remover itens de um dicionário. Ambos mudam o dicionário original, então você precisa fazer uma cópia (veja detalhes abaixo).E os dois irão gerar um
KeyError
se a chave que você está fornecendo a eles não estiver presente no dicionário:e
Você tem que cuidar disso:
capturando a exceção:
e
executando uma verificação:
e
mas
pop()
também há uma maneira muito mais concisa - forneça o valor de retorno padrão:A menos que você use
pop()
para obter o valor de uma chave sendo removida, você pode fornecer qualquer coisa, não necessárioNone
. Embora possa ser que o usodel
comin
cheque seja um pouco mais rápido devido apop()
uma função com suas próprias complicações causando sobrecarga. Normalmente não é o caso, portanto,pop()
com o valor padrão é bom o suficiente.Quanto à pergunta principal, você terá que fazer uma cópia do seu dicionário, salvar o dicionário original e ter um novo sem a chave ser removida.
Algumas outras pessoas aqui sugerem fazer uma cópia completa (profunda) com
copy.deepcopy()
, que pode ser um exagero, uma cópia "normal" (superficial), usandocopy.copy()
oudict.copy()
, pode ser suficiente. O dicionário mantém uma referência ao objeto como um valor para uma chave. Portanto, quando você remove uma chave de um dicionário, essa referência é removida, não o objeto que está sendo referenciado. O próprio objeto pode ser removido posteriormente automaticamente pelo coletor de lixo, se não houver outras referências para ele na memória. Fazer uma cópia profunda requer mais cálculos em comparação com a cópia superficial; portanto, diminui o desempenho do código ao fazer a cópia, desperdiçando memória e fornecendo mais trabalho ao GC; às vezes, a cópia superficial é suficiente.No entanto, se você tiver objetos mutáveis como valores do dicionário e planeja modificá-los posteriormente no dicionário retornado sem a chave, precisará fazer uma cópia profunda.
Com cópia rasa:
Com cópia profunda:
fonte
A
dict
é a estrutura de dados incorreta a ser usada para isso.Certamente, copiar o ditado e saltar da cópia funciona, assim como construir um novo ditado com compreensão, mas toda essa cópia leva tempo - você substituiu uma operação de tempo constante por uma linear. E todas essas cópias vivas ao mesmo tempo ocupam espaço - espaço linear por cópia.
Outras estruturas de dados, como tentativas mapeadas de matriz de hash , são projetadas exatamente para esse tipo de caso de uso: adicionar ou remover um elemento retorna uma cópia em tempo logarítmico, compartilhando a maior parte de seu armazenamento com o original . 1
Claro que existem algumas desvantagens. O desempenho é logarítmico e não constante (embora com uma base grande, geralmente de 32 a 128). E, embora você possa tornar a API sem mutação idêntica à
dict
, a API "mutante" é obviamente diferente. E, acima de tudo, não há baterias HAMT incluídas no Python. 2A
pyrsistent
biblioteca é uma implementação bastante sólida de substituições de dict baseadas em HAMT (e vários outros tipos) para Python. Ele ainda possui uma API do evolver bacana para transportar o código mutante existente para o código persistente da maneira mais suave possível. Mas se você quiser ser explícito sobre o retorno de cópias em vez de fazer a mutação, use-o assim:É
d3 = d1.remove('a')
exatamente isso que a pergunta está pedindo.Se você tiver estruturas de dados mutáveis como
dict
elist
incorporadas aopmap
, ainda terá problemas de alias - você só pode consertar isso imutável até o fim, incorporandopmap
s epvector
s.1. Os HAMTs também se tornaram populares em linguagens como Scala, Clojure e Haskell, porque jogam muito bem com programação livre de bloqueios e memória transacional de software, mas nenhum deles é muito relevante no Python.
2. Na verdade, não é uma Hamt no stdlib, utilizados na execução de
contextvars
. O PEP retirado anteriormente explica o porquê. Mas esse é um detalhe de implementação oculto da biblioteca, não um tipo de coleção pública.fonte
Resultado:
d = {1: 2, '2': 3}
fonte
Simplesmente chame del d ['chave'].
No entanto, na produção, é sempre uma boa prática verificar se 'chave' existe em d.
fonte
try-except
bloco. Pelo menos, esta será uma operação atômica;)d.pop('key', None)
, use , é um delineador. Mas a questão real era sobre obter o dicionário sem uma chave e não modificar o ditado. Então compreensões - é uma boa escolha aqui;)Não, não há outra maneira senão
No entanto, criar cópias de dicionários apenas ligeiramente alterados provavelmente não é uma boa ideia, pois resultará em demandas de memória comparativamente grandes. Geralmente é melhor registrar o dicionário antigo (se necessário) e modificá-lo.
fonte
fonte
isso não faz nenhum tratamento de erros, assume que a chave está no ditado, você pode verificar isso primeiro e
raise
se não estiverfonte
del test_dict[key]
?Aqui está uma abordagem de design de nível superior:
Estou passando o dicionário e a chave que desejo para minha função, valida se é um dicionário e se a chave está correta e, se ambas existirem, remove o valor do dicionário e imprime as sobras.
Resultado:
{'B': 55, 'A': 34}
Espero que ajude!
fonte
Abaixo o snippet de código o ajudará definitivamente, adicionei comentários em cada linha que ajudarão você a entender o código.
ou você também pode usar dict.pop ()
ou a melhor abordagem é
fonte
Aqui está outra variação usando a compreensão da lista:
A abordagem é baseada em uma resposta deste post: Maneira eficiente de remover chaves com strings vazias de um dict
fonte
if v
paraif k is not 'a'
responder ao op. Mas eu não acho que seja uma maneira eficiente, isso remove o elemento em O (n) em vez de O (log n) como pop ou del.O código a seguir fará uma cópia do dict
species
e excluirá os itens que não estão notrans_HI
fonte