Come rimuovere una chiave da un dizionario Python?


Risposte:


2842

Per eliminare una chiave indipendentemente dal fatto che sia presente nel dizionario, utilizzare la forma a due argomenti di dict.pop():

my_dict.pop('key', None)

Questo restituirà my_dict[key]se keyesiste nel dizionario e in caso Nonecontrario. Se il secondo parametro non è specificato (es. my_dict.pop('key')) E keynon esiste, KeyErrorviene sollevato a.

Per eliminare una chiave garantita, è anche possibile utilizzare

del my_dict['key']

Questo aumenterà a KeyErrorse la chiave non è nel dizionario.


153
A volte un vantaggio dell'uso di pop()over del: restituisce il valore per quella chiave. In questo modo è possibile ottenere ed eliminare una voce da un dict in una riga di codice.
Kratenko,

7
Nella domanda non è necessario mantenere il valore. Ciò aggiungerebbe solo complessità non necessaria. La risposta di @zigg (sotto) è molto migliore.
Salvatore Cosentino,

10
@SalvatoreCosentino Non riesco a seguire il tuo argomento. In che modo il codice in questa risposta è più complesso del codice nell'altra risposta?
Sven Marnach,

33
@SalvatoreCosentino No, ignorare il valore di ritorno di una funzione non è affatto inefficiente. Al contrario, questa soluzione è molto più veloce della soluzione try/ exceptse la chiave non esiste. Potresti trovare l'uno o l'altro più facile da leggere, il che va bene. Entrambi sono idiomatici Python, quindi scegli quello che preferisci. Ma affermare che questa risposta è più complessa o inefficiente semplicemente non ha senso.
Sven Marnach,

5
@ user5359531 Non capisco. Come è questo un problema? Nessuno dei metodi sui tipi predefiniti di Python ritorna self, quindi sarebbe piuttosto sorprendente se questo lo facesse.
Sven Marnach,

353

In particolare per rispondere "esiste un modo di fare una linea per farlo?"

if 'key' in my_dict: del my_dict['key']

... bene, hai chiesto ;-)

Dovresti considerare, tuttavia, che questo modo di eliminare un oggetto da un nondict è atomico: è possibile che 'key'sia presente my_dictdurante l' ifistruzione, ma che possa essere eliminato prima che delvenga eseguito, nel qual caso delfallirà con a KeyError. Detto questo, sarebbe più sicuro usaredict.pop o qualcosa del genere

try:
    del my_dict['key']
except KeyError:
    pass

che, naturalmente, è sicuramente non una battuta.


27
Sì, popè decisamente più conciso, anche se c'è un vantaggio chiave nel farlo in questo modo: è immediatamente chiaro cosa sta facendo.
zigg,

4
La try/exceptdichiarazione è più costosa. Sollevare un'eccezione è lento.
Chris Barker,

16
@ChrisBarker Ho scoperto che la chiave esiste, tryè leggermente più veloce, anche se in caso contrario tryè molto più lenta. popè abbastanza coerente ma più lento di tutti ma trycon una chiave non presente. Vedi gist.github.com/zigg/6280653 . In definitiva, dipende dalla frequenza con cui ti aspetti che la chiave sia effettivamente nel dizionario e se hai bisogno dell'atomicità o meno e, naturalmente, se ti impegni o meno nell'ottimizzazione prematura;)
zigg

9
Credo che il valore della chiarezza non debba essere trascurato. +1 per questo.
Juan Carlos Coto,

2
per quanto riguarda le spese di prova / tranne, puoi anche andare if 'key' in mydict: #then del.... Avevo bisogno di estrarre una chiave / val da un dict per analizzare correttamente, il pop non era una soluzione perfetta.
Marc

153

Mi ci è voluto del tempo per capire cosa stesse my_dict.pop("key", None)facendo esattamente . Quindi aggiungerò questo come risposta per salvare gli altri.

pop(key[, default])

Se la chiave è nel dizionario, rimuoverla e restituire il suo valore, altrimenti restituisce il valore predefinito . Se non viene fornito il valore predefinito e la chiave non è presente nel dizionario, KeyErrorviene sollevato a.

Documentazione


15
Digita help (dict.pop) nell'interprete python.
David Mulder,

13
help () e dir () possono essere i tuoi amici quando devi sapere cosa fa qualcosa.
David Mulder,

3
o dict.pop?in IPython.
Erik Kaplun,

51

del my_dict[key]è leggermente più veloce rispetto my_dict.pop(key)alla rimozione di una chiave da un dizionario quando esiste la chiave

>>> import timeit
>>> setup = "d = {i: i for i in range(100000)}"

>>> timeit.timeit("del d[3]", setup=setup, number=1)
1.79e-06
>>> timeit.timeit("d.pop(3)", setup=setup, number=1)
2.09e-06
>>> timeit.timeit("d2 = {key: val for key, val in d.items() if key != 3}", setup=setup, number=1)
0.00786

Ma quando la chiave non esiste if key in my_dict: del my_dict[key]è leggermente più veloce di my_dict.pop(key, None). Entrambi sono almeno tre volte più veloci che delin un'istruzione try/ except:

>>> timeit.timeit("if 'missing key' in d: del d['missing key']", setup=setup)
0.0229
>>> timeit.timeit("d.pop('missing key', None)", setup=setup)
0.0426
>>> try_except = """
... try:
...     del d['missing key']
... except KeyError:
...     pass
... """
>>> timeit.timeit(try_except, setup=setup)
0.133

1
Misurare i tempi di un'operazione così rapida è piuttosto stupido. Il tuo codice probabilmente non diventerà molto più veloce perché hai cambiato a popin a del. La creazione del dizionario eliminerà completamente la cancellazione di cose da esso.
Boris,

1
@Boris - questo è utile come esercizio generale.
margherita il

1
@daisy quello che sto dicendo è che dovresti scegliere la sintassi più leggibile, non l'operazione che è 300 nanosecondi più veloce (questa è letteralmente la differenza tra dele popdalla prima serie di tempi sopra)
Boris

Anche queste operazioni sono così veloci che questi tempi non sono affidabili.
Boris,

46

Se devi rimuovere molte chiavi da un dizionario in una riga di codice, penso che usare map () sia abbastanza sintetico e leggibile da Pythonic:

myDict = {'a':1,'b':2,'c':3,'d':4}
map(myDict.pop, ['a','c']) # The list of keys to remove
>>> myDict
{'b': 2, 'd': 4}

E se hai bisogno di rilevare errori in cui fai apparire un valore che non è nel dizionario, usa lambda inside map () in questo modo:

map(lambda x: myDict.pop(x,None), ['a', 'c', 'e'])
[1, 3, None] # pop returns
>>> myDict
{'b': 2, 'd': 4}

o in python3, invece, è necessario utilizzare una comprensione dell'elenco:

[myDict.pop(x, None) for x in ['a', 'c', 'e']]

Funziona. E 'e' non ha causato errori, anche se myDict non aveva un tasto 'e'.


42
Questo non funzionerà in Python 3 perché mapora gli amici sono pigri e restituiscono iteratori. L'uso mapper gli effetti collaterali è generalmente considerato una cattiva pratica; un for ... inciclo standard sarebbe meglio. Per ulteriori informazioni, consultare Visualizzazioni e iteratori anziché elenchi .
Greg Krimer,

5
Indipendentemente dal gusto e dallo stile di pratica, la comprensione dell'elenco dovrebbe ancora funzionare in Py3 [myDict.pop(i, None) for i in ['a', 'c']], poiché offre un'alternativa generale a map(e filter).
Michael Ekoka,

@MichaelEkoka non dovresti usare la comprensione dell'elenco per i loro effetti collaterali, usa un for ... inciclo regolare .
Boris,

@Boris Probabilmente hai ragione. La mia risposta riguarda specificamente l'utilizzo map(), che viene spesso utilizzato per i suoi effetti collaterali. L'alternativa raccomandata in Python è la comprensione dell'elenco, che secondo me è ancora abbastanza leggibile e cognitivamente leggera come una riga (vedi domanda). Utilizzati solo per i loro effetti collaterali, entrambi i costrutti risultano in un elenco inutile, che può essere inefficiente. A partire da Python3, non sono a conoscenza di una funzione integrata che può iterare in modo sicuro ed elegante attraverso un'espressione del generatore, senza un sottoprodotto costoso, ad es loop(d.pop(k) for k in ['a', 'b']).
Michael Ekoka,

Sono divertito dal fatto che la mia risposta più votata di sempre includa alcuni hack che non userei mai. La comprensione dell'elenco (opzione 3) è l'approccio meno negativo, a mio avviso. Usa quello.
Marc Maxmeister,

20

È possibile utilizzare una comprensione del dizionario per creare un nuovo dizionario con quella chiave rimossa:

>>> my_dict = {k: v for k, v in my_dict.items() if k != 'key'}

È possibile eliminare in base alle condizioni. Nessun errore se keynon esiste.



7

Possiamo eliminare una chiave da un dizionario Python con i seguenti approcci.

Utilizzando la delparola chiave; è quasi lo stesso approccio che hai fatto però -

 myDict = {'one': 100, 'two': 200, 'three': 300 }
 print(myDict)  # {'one': 100, 'two': 200, 'three': 300}
 if myDict.get('one') : del myDict['one']
 print(myDict)  # {'two': 200, 'three': 300}

O

Possiamo fare come segue:

Ma bisogna tenere presente che, in questo processo, in realtà non eliminerà alcuna chiave dal dizionario piuttosto che escludere una chiave specifica da quel dizionario. Inoltre, ho osservato che restituiva un dizionario che non era stato ordinato come myDict.

myDict = {'one': 100, 'two': 200, 'three': 300, 'four': 400, 'five': 500}
{key:value for key, value in myDict.items() if key != 'one'}

Se lo eseguiamo nella shell, eseguirà qualcosa del genere {'five': 500, 'four': 400, 'three': 300, 'two': 200}- nota che non è lo stesso ordinato myDict. Ancora una volta, se proviamo a stampare myDict, possiamo vedere tutte le chiavi incluse quelle che abbiamo escluso dal dizionario con questo approccio. Tuttavia, possiamo creare un nuovo dizionario assegnando la seguente istruzione in una variabile:

var = {key:value for key, value in myDict.items() if key != 'one'}

Ora se proviamo a stamparlo, seguirà l'ordine parent:

print(var) # {'two': 200, 'three': 300, 'four': 400, 'five': 500}

O

Utilizzando il pop()metodo

myDict = {'one': 100, 'two': 200, 'three': 300}
print(myDict)

if myDict.get('one') : myDict.pop('one')
print(myDict)  # {'two': 200, 'three': 300}

La differenza tra dele popè che, usando il pop()metodo, possiamo effettivamente memorizzare il valore della chiave se necessario, come il seguente:

myDict = {'one': 100, 'two': 200, 'three': 300}
if myDict.get('one') : var = myDict.pop('one')
print(myDict) # {'two': 200, 'three': 300}
print(var)    # 100

Fork questa sostanza per riferimento futuro, se lo trovi utile.


1
Non usare if myDict.get('one')per verificare se è presente una chiave! Non riesce se myDict ['one'] ha un valore false. Inoltre, i dadi non hanno un ordine intrinseco, quindi non ha senso menzionarlo.
Rob,

I dicts @Rob sono ordinati per ordine di inserzione a partire da CPython 3.6 e tutte le altre implementazioni di Python a partire da 3.7.
Boris,

4

Puoi usare la gestione delle eccezioni se vuoi essere molto dettagliato:

try: 
    del dict[key]

except KeyError: pass

Questo è più lento, tuttavia, rispetto al pop()metodo, se la chiave non esiste.

my_dict.pop('key', None)

Non importa per alcune chiavi, ma se lo fai ripetutamente, quest'ultimo metodo è una scommessa migliore.

L'approccio più veloce è questo:

if 'key' in dict: 
    del myDict['key']

Ma questo metodo è pericoloso perché se 'key'viene rimosso tra le due linee, KeyErrorverrà sollevato un.


1

Preferisco la versione immutabile

foo = {
    1:1,
    2:2,
    3:3
}
removeKeys = [1,2]
def woKeys(dct, keyIter):
    return {
        k:v
        for k,v in dct.items() if k not in keyIter
    }

>>> print(woKeys(foo, removeKeys))
{3: 3}
>>> print(foo)
{1: 1, 2: 2, 3: 3}

1

Un altro modo consiste nell'usare items () + comprensione di dict

items () accoppiato con la comprensione di dict può anche aiutarci a raggiungere il compito della cancellazione della coppia chiave-valore ma, ha lo svantaggio di non essere una tecnica di dict sul posto. In realtà un nuovo dict se creato ad eccezione della chiave che non desideriamo includere.

test_dict = {"sai" : 22, "kiran" : 21, "vinod" : 21, "sangam" : 21} 

# Printing dictionary before removal 
print ("dictionary before performing remove is : " + str(test_dict)) 

# Using items() + dict comprehension to remove a dict. pair 
# removes  vinod
new_dict = {key:val for key, val in test_dict.items() if key != 'vinod'} 

# Printing dictionary after removal 
print ("dictionary after remove is : " + str(new_dict)) 

Produzione:

dictionary before performing remove is : {'sai': 22, 'kiran': 21, 'vinod': 21, 'sangam': 21}
dictionary after remove is : {'sai': 22, 'kiran': 21, 'sangam': 21}

0

Filtro singolo su chiave

  • restituisce "chiave" e rimuoverlo da my_dict se "chiave" esiste in my_dict
  • return Nessuno se "chiave" non esiste in my_dict

questo cambierà my_dictsul posto (mutevole)

my_dict.pop('key', None)

Più filtri sui tasti

generare un nuovo dict (immutabile)

dic1 = {
    "x":1,
    "y": 2,
    "z": 3
}

def func1(item):
    return  item[0]!= "x" and item[0] != "y"

print(
    dict(
        filter(
            lambda item: item[0] != "x" and item[0] != "y", 
            dic1.items()
            )
    )
)
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.