Eu tenho um dict
que tem um monte de entradas. Estou interessado apenas em alguns deles selecionados. Existe uma maneira fácil de remover todos os outros?
Eu tenho um dict
que tem um monte de entradas. Estou interessado apenas em alguns deles selecionados. Existe uma maneira fácil de remover todos os outros?
Respostas:
Construindo um novo ditado:
dict_you_want = { your_key: old_dict[your_key] for your_key in your_keys }
Usa compreensão de dicionário.
Se você usa uma versão que não possui (por exemplo, Python 2.6 e anterior), faça-o dict((your_key, old_dict[your_key]) for ...)
. É o mesmo, embora mais feio.
Observe que isso, diferente da versão do jnnnnn, tem desempenho estável (depende apenas do número de suas_chaves) para old_dict
s de qualquer tamanho. Tanto em termos de velocidade e memória. Como essa é uma expressão geradora, ele processa um item de cada vez e não analisa todos os itens do old_dict.
Removendo tudo no local:
unwanted = set(keys) - set(your_dict)
for unwanted_key in unwanted: del your_dict[unwanted_key]
old_dict
indica um erro em outro lugar e, nesse caso, eu prefiro um erro a resultados silenciosamente errados.
Compreensão de ditado um pouco mais elegante:
foodict = {k: v for k, v in mydict.items() if k.startswith('foo')}
mydict.iteritems()
. .items()
cria outra lista.
Aqui está um exemplo no python 2.6:
>>> a = {1:1, 2:2, 3:3}
>>> dict((key,value) for key, value in a.iteritems() if key == 1)
{1: 1}
A parte de filtragem é a if
declaração.
Esse método é mais lento que a resposta de delnan, se você deseja selecionar apenas algumas das muitas teclas.
if key in ('x','y','z')
eu acho.
Você pode fazer isso com a função de projeto da minha biblioteca de funções :
from funcy import project
small_dict = project(big_dict, keys)
Veja também select_keys .
Código 1:
dict = { key: key * 10 for key in range(0, 100) }
d1 = {}
for key, value in dict.items():
if key % 2 == 0:
d1[key] = value
Código 2:
dict = { key: key * 10 for key in range(0, 100) }
d2 = {key: value for key, value in dict.items() if key % 2 == 0}
Código 3:
dict = { key: key * 10 for key in range(0, 100) }
d3 = { key: dict[key] for key in dict.keys() if key % 2 == 0}
Todo o desempenho do código é medido com timeit usando número = 1000 e coletado 1000 vezes para cada código.
Para o python 3.6, o desempenho de três formas de chaves de filtro é quase o mesmo. Para o python 2.7, o código 3 é um pouco mais rápido.
Este lambda de um liner deve funcionar:
dictfilt = lambda x, y: dict([ (i,x[i]) for i in x if i in set(y) ])
Aqui está um exemplo:
my_dict = {"a":1,"b":2,"c":3,"d":4}
wanted_keys = ("c","d")
# run it
In [10]: dictfilt(my_dict, wanted_keys)
Out[10]: {'c': 3, 'd': 4}
É uma compreensão básica da lista que itera sobre as chaves de ditado (i em x) e gera uma lista de pares de tupla (chave, valor) se a chave estiver na lista de chaves desejada (y). Um dict () envolve a coisa toda para produzir como um objeto dict.
set
para wanted_keys
, mas parece bom.
dictfilt({'x':['wefwef',52],'y':['iuefiuef','efefij'],'z':['oiejf','iejf']}, ('x','z'))
:, ele retornará {'x': ['wefwef', 52], 'z': ['oiejf', 'iejf']}
como pretendido.
dict={'0':[1,3], '1':[0,2,4], '2':[1,4]}
e o resultado foi {}
, que eu assumi ser um ditado em branco.
foo = {'0':[1,3], '1':[0,2,4], '2':[1,4]}; dictfilt(foo,('0','2'))
, eu recebo: {'0': [1, 3], '2': [1, 4]}
que é o resultado pretendido
Dado o seu dicionário original orig
e o conjunto de entradas em que você está interessado keys
:
filtered = dict(zip(keys, [orig[k] for k in keys]))
o que não é tão bom quanto a resposta de delnan, mas deve funcionar em todas as versões de interesse do Python. É, no entanto, frágil para cada elemento keys
existente no seu dicionário original.
Com base na resposta aceita por delnan.
E se uma de suas chaves desejadas não estiver no old_dict? A solução delnan lançará uma exceção KeyError que você pode capturar. Se não é isso que você precisa, talvez você queira:
inclua apenas chaves que existam tanto no ditado antigo quanto no seu conjunto de chaves desejadas.
old_dict = {'name':"Foobar", 'baz':42}
wanted_keys = ['name', 'age']
new_dict = {k: old_dict[k] for k in set(wanted_keys) & set(old_dict.keys())}
>>> new_dict
{'name': 'Foobar'}
tem um valor padrão para chaves que não está definido no old_dict.
default = None
new_dict = {k: old_dict[k] if k in old_dict else default for k in wanted_keys}
>>> new_dict
{'age': None, 'name': 'Foobar'}
{k: old_dict.get(k, default) for k in ...}
Esta função fará o truque:
def include_keys(dictionary, keys):
"""Filters a dict by only including certain keys."""
key_set = set(keys) & set(dictionary.keys())
return {key: dictionary[key] for key in key_set}
Assim como a versão de delnan, esta usa compreensão de dicionário e tem desempenho estável para dicionários grandes (depende apenas do número de chaves que você permite, e não do número total de chaves no dicionário).
E, assim como a versão do MyGGan, esta permite que sua lista de chaves inclua chaves que podem não existir no dicionário.
E como bônus, aqui está o inverso, onde você pode criar um dicionário excluindo determinadas chaves no original:
def exclude_keys(dictionary, keys):
"""Filters a dict by excluding certain keys."""
key_set = set(dictionary.keys()) - set(keys)
return {key: dictionary[key] for key in key_set}
Observe que, diferentemente da versão do delnan, a operação não é realizada no local, portanto o desempenho está relacionado ao número de chaves no dicionário. No entanto, a vantagem disso é que a função não modifica o dicionário fornecido.
Editar: adicionada uma função separada para excluir determinadas teclas de um ditado.
invert
implica que o keys
argumento seja mantido ou que o keys
argumento seja rejeitado?", Quantas delas concordariam?
Se queremos criar um novo dicionário com as chaves selecionadas removidas, podemos fazer uso da compreensão do dicionário.
Por exemplo:
d = {
'a' : 1,
'b' : 2,
'c' : 3
}
x = {key:d[key] for key in d.keys() - {'c', 'e'}} # Python 3
y = {key:d[key] for key in set(d.keys()) - {'c', 'e'}} # Python 2.*
# x is {'a': 1, 'b': 2}
# y is {'a': 1, 'b': 2}
Outra opção:
content = dict(k1='foo', k2='nope', k3='bar')
selection = ['k1', 'k3']
filtered = filter(lambda i: i[0] in selection, content.items())
Mas você obtém um list
(Python 2) ou um iterador (Python 3) retornado por filter()
, não um dict
.
filtered
em dict
e você recebe de volta o dicionário!
Aqui está outro método simples usando del
em um forro:
for key in e_keys: del your_dict[key]
e_keys
é a lista das chaves a serem excluídas. Ele atualizará seu ditado em vez de fornecer um novo.
Se você deseja um novo dict de saída, faça uma cópia do dict antes de excluir:
new_dict = your_dict.copy() #Making copy of dict
for key in e_keys: del new_dict[key]
Você poderia usar python-benedict
, é uma subclasse dict.
Instalação: pip install python-benedict
from benedict import benedict
dict_you_want = benedict(your_dict).subset(keys=['firstname', 'lastname', 'email'])
É de código aberto no GitHub: https://github.com/fabiocaccamo/python-benedict
Isenção de responsabilidade: sou o autor desta biblioteca.