Ho un dict
che ha un sacco di voci. Sono interessato solo ad alcuni selezionati. C'è un modo semplice per eliminare tutti gli altri?
Ho un dict
che ha un sacco di voci. Sono interessato solo ad alcuni selezionati. C'è un modo semplice per eliminare tutti gli altri?
Risposte:
Costruire un nuovo dict:
dict_you_want = { your_key: old_dict[your_key] for your_key in your_keys }
Usa la comprensione del dizionario.
Se usi una versione che le manca (cioè Python 2.6 e precedenti), fallo dict((your_key, old_dict[your_key]) for ...)
. È lo stesso, anche se più brutto.
Nota che questo, a differenza della versione di jnnnnn, ha prestazioni stabili (dipende solo dal numero di your_keys) per le old_dict
s di qualsiasi dimensione. Sia in termini di velocità che di memoria. Poiché si tratta di un'espressione del generatore, elabora un elemento alla volta e non esamina tutti gli elementi di old_dict.
Rimozione di tutto sul posto:
unwanted = set(keys) - set(your_dict)
for unwanted_key in unwanted: del your_dict[unwanted_key]
old_dict
indica un bug altrove, e in quel caso preferisco di gran lunga un errore a risultati silenziosamente errati.
Comprensione del dict leggermente più elegante:
foodict = {k: v for k, v in mydict.items() if k.startswith('foo')}
mydict.iteritems()
invece lo usassi. .items()
crea un altro elenco.
Ecco un esempio in Python 2.6:
>>> a = {1:1, 2:2, 3:3}
>>> dict((key,value) for key, value in a.iteritems() if key == 1)
{1: 1}
La parte di filtro è l' if
istruzione.
Questo metodo è più lento della risposta di Delnan se si desidera selezionare solo alcuni dei moltissimi tasti.
if key in ('x','y','z')
immagino.
Codice 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
Codice 2:
dict = { key: key * 10 for key in range(0, 100) }
d2 = {key: value for key, value in dict.items() if key % 2 == 0}
Codice 3:
dict = { key: key * 10 for key in range(0, 100) }
d3 = { key: dict[key] for key in dict.keys() if key % 2 == 0}
Tutte le prestazioni del codice sono misurate con timeit usando il numero = 1000 e raccolte 1000 volte per ogni pezzo di codice.
Per python 3.6 le prestazioni di tre modi di filtrare le chiavi di comando sono quasi le stesse. Per python 2.7 il codice 3 è leggermente più veloce.
Questa liner lambda dovrebbe funzionare:
dictfilt = lambda x, y: dict([ (i,x[i]) for i in x if i in set(y) ])
Ecco un esempio:
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}
È una comprensione di base dell'elenco che scorre sulle tue chiavi dict (i in x) e genera un elenco di coppie tuple (chiave, valore) se la chiave risiede nell'elenco delle chiavi desiderato (y). Un dict () racchiude il tutto in output come oggetto dict.
set
per wanted_keys
, ma per il resto sembra buono.
dictfilt({'x':['wefwef',52],'y':['iuefiuef','efefij'],'z':['oiejf','iejf']}, ('x','z'))
:, ritorna {'x': ['wefwef', 52], 'z': ['oiejf', 'iejf']}
come previsto.
dict={'0':[1,3], '1':[0,2,4], '2':[1,4]}
e il risultato è stato {}
, che ho assunto come un dict in bianco.
foo = {'0':[1,3], '1':[0,2,4], '2':[1,4]}; dictfilt(foo,('0','2'))
:, ottengo: {'0': [1, 3], '2': [1, 4]}
qual è il risultato previsto
Dato il dizionario originale orig
e il set di voci che ti interessano keys
:
filtered = dict(zip(keys, [orig[k] for k in keys]))
che non è bello come la risposta di Delnan, ma dovrebbe funzionare in ogni versione di Python di interesse. È, tuttavia, fragile per ogni elemento dikeys
esistente nel dizionario originale.
Basato sulla risposta accettata di delnan.
E se una delle tue chiavi desiderate non fosse nel vecchio_dict? La soluzione delnan genererà un'eccezione KeyError che puoi rilevare. Se non è quello che ti serve, forse vuoi:
includi solo le chiavi che eccitano sia in old_dict sia nel tuo set di wanted_keys.
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'}
avere un valore predefinito per le chiavi che non è impostato in 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 ...}
Questa funzione farà il trucco:
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}
Proprio come la versione di Delnan, questa utilizza la comprensione del dizionario e ha prestazioni stabili per dizionari di grandi dimensioni (dipende solo dal numero di chiavi consentite e non dal numero totale di chiavi nel dizionario).
E proprio come la versione di MyGGan, questa consente al tuo elenco di chiavi di includere chiavi che potrebbero non esistere nel dizionario.
E come bonus, ecco l'inverso, dove puoi creare un dizionario escludendo alcune chiavi nell'originale:
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}
Notare che a differenza della versione di Delnan, l'operazione non viene eseguita sul posto, quindi le prestazioni sono correlate al numero di chiavi nel dizionario. Tuttavia, il vantaggio è che la funzione non modificherà il dizionario fornito.
Modifica: aggiunta una funzione separata per escludere determinati tasti da un dict.
invert
implica che l' keys
argomento è mantenuto o che l' keys
argomento è respinto?", Quanti di loro sarebbero d'accordo?
Se vogliamo creare un nuovo dizionario con le chiavi selezionate rimosse, possiamo fare uso della comprensione del dizionario
Ad esempio:
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}
Un'altra opzione:
content = dict(k1='foo', k2='nope', k3='bar')
selection = ['k1', 'k3']
filtered = filter(lambda i: i[0] in selection, content.items())
Ma ricevi un list
(Python 2) o un iteratore (Python 3) restituito filter()
, non un dict
.
filtered
in dict
e si ottiene indietro il dizionario!
Ecco un altro metodo semplice che utilizza del
in un liner:
for key in e_keys: del your_dict[key]
e_keys
è l'elenco delle chiavi da escludere. Aggiornerà il tuo dict piuttosto che dartene uno nuovo.
Se vuoi un nuovo dict di output, crea una copia del dict prima di eliminare:
new_dict = your_dict.copy() #Making copy of dict
for key in e_keys: del new_dict[key]
È possibile utilizzare python-benedict
, è una sottoclasse dict.
Installazione: pip install python-benedict
from benedict import benedict
dict_you_want = benedict(your_dict).subset(keys=['firstname', 'lastname', 'email'])
È open-source su GitHub: https://github.com/fabiocaccamo/python-benedict
Disclaimer: sono l'autore di questa biblioteca.