Jak usunąć klucz ze słownika Python?

Odpowiedzi:

2833

Aby usunąć klucz bez względu na to, czy znajduje się w słowniku, użyj dwuargumentowej formy dict.pop():

my_dict.pop('key', None)

Zwróci to, my_dict[key]jeśli keyistnieje w słowniku i Noneinaczej. Jeśli drugi parametr nie jest określony (tj. my_dict.pop('key')) I keynie istnieje, to KeyErrorjest wywoływane a.

Aby usunąć klucz, który na pewno istnieje, możesz również użyć

del my_dict['key']

Spowoduje to podniesienie a, KeyErrorjeśli klucza nie ma w słowniku.

Sven Marnach
źródło
152
Czasami zaletą używania pop()over del: zwraca wartość tego klucza. W ten sposób możesz pobrać i usunąć wpis ze słownika w jednym wierszu kodu.
kratenko,
7
W pytaniu nie jest wymagane zachowanie wartości. To tylko zwiększyłoby niepotrzebną złożoność. Odpowiedź z @zigg (poniżej) jest znacznie lepsza.
Salvatore Cosentino
10
@SalvatoreCosentino Nie mogę śledzić twojego argumentu. W jaki sposób kod w tej odpowiedzi jest bardziej złożony niż kod w drugiej odpowiedzi?
Sven Marnach,
33
@SalvatoreCosentino Nie, ignorowanie zwracanej wartości funkcji nie jest wcale nieefektywne. Wręcz przeciwnie - to rozwiązanie jest znacznie szybsze niż rozwiązanie try/ except, jeśli klucz nie istnieje. Możesz znaleźć jedno lub drugie łatwiejsze do odczytania, co jest w porządku. Oba są idiomatycznym Pythonem, więc wybierz, co wolisz. Ale twierdzenie, że ta odpowiedź jest bardziej złożona lub nieefektywna, po prostu nie ma sensu.
Sven Marnach,
5
@ user5359531 Nie rozumiem. Jak to jest problem? Żadna z metod wbudowanych typów Pythona nie zwraca self, więc byłoby raczej zaskakujące, gdyby to zrobiła.
Sven Marnach
352

W szczególności, aby odpowiedzieć „czy istnieje jeden sposób na zrobienie tego?”

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

... cóż, zapytałeś ;-)

Należy jednak wziąć pod uwagę, że ten sposób usuwania obiektu z niedict jest atomowy - możliwe, że 'key'może to być my_dictpodczas ifinstrukcji, ale może zostać usunięte przed delwykonaniem, w którym to przypadku delzakończy się niepowodzeniem za pomocą KeyError. Biorąc to pod uwagę, najbezpieczniej byłoby użyćdict.pop albo coś w tym stylu

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

co oczywiście nie jest jednoskładnikowe.

zigg
źródło
27
Tak, popjest zdecydowanie bardziej zwięzły, chociaż jest jedna kluczowa zaleta robienia tego w ten sposób: od razu wiadomo, co robi.
zigg
4
try/exceptStwierdzenie jest droższe. Zgłaszanie wyjątku jest powolne.
Chris Barker,
16
@ChrisBarker Dowiedziałem się, że jeśli klucz istnieje, tryjest nieznacznie szybszy, choć jeśli nie, tryjest rzeczywiście znacznie wolniejszy. popjest dość spójny, ale wolniejszy niż wszystkie, ale tryz nieobecnym kluczem. Zobacz gist.github.com/zigg/6280653 . Ostatecznie, to zależy od tego, jak często można się spodziewać klucz do rzeczywiście być w słowniku, i czy nie trzeba niepodzielność-i, oczywiście, czy nie jesteś angażowanie przedwczesne optymalizacji;)
zigg
9
Uważam, że nie można przeoczyć wartości przejrzystości. +1 za to.
Juan Carlos Coto
2
jeśli chodzi o koszt wypróbowania / z wyjątkiem, możesz również przejść if 'key' in mydict: #then del.... Musiałem wyciągnąć klucz / val ze słownika, aby poprawnie parsować, pop nie był idealnym rozwiązaniem.
Marc
152

Zajęło mi trochę czasu, aby dowiedzieć się, co dokładnie my_dict.pop("key", None)robi. Dodaję to jako odpowiedź, aby zaoszczędzić czas innym użytkownikom Google:

pop(key[, default])

Jeśli klucz znajduje się w słowniku, usuń go i zwróć jego wartość, w przeciwnym razie zwróć wartość domyślną . Jeśli wartość domyślna nie jest podana, a klucza nie ma w słowniku, KeyErrorzostanie podniesiona wartość a.

Dokumentacja

Akavall
źródło
15
Po prostu wpisz help (dict.pop) w interpreterie Pythona.
David Mulder
13
help () i dir () mogą być twoimi przyjaciółmi, gdy musisz wiedzieć, co coś robi.
David Mulder
3
lub dict.pop?w IPython.
Erik Kaplun,
50

del my_dict[key]jest nieco szybszy niż w my_dict.pop(key)przypadku usuwania klucza ze słownika, gdy klucz istnieje

>>> 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

Ale kiedy klucz nie istnieje, if key in my_dict: del my_dict[key]jest nieco szybszy niż my_dict.pop(key, None). Oba są co najmniej trzy razy szybsze niż delw instrukcji 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
Peter Smit
źródło
1
Mierzenie czasu tak szybkiej operacji jest dość głupie. Twój kod prawdopodobnie nie będzie dużo szybszy, ponieważ zmieniłeś popna a del. Utworzenie słownika całkowicie przyćmiewa usuwanie z niego rzeczy.
Boris
1
@ Boris - jest to przydatne jako ogólne ćwiczenie.
stokrotka
1
@daisy co mówię jest to, że należy wybrać najbardziej czytelny nie Składnia operację, która wynosi 300 nanosekund szybciej (to dosłownie różnica między deli popod pierwszego zestawu taktowania powyżej)
Boris
Również te operacje są tak szybkie, że te czasy nie są wiarygodne.
Boris
45

Jeśli chcesz usunąć wiele kluczy ze słownika w jednym wierszu kodu, myślę, że użycie map () jest dość zwięzłe i czytelne w języku Python:

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}

A jeśli chcesz wychwycić błędy, w których wpisujesz wartość, której nie ma w słowniku, użyj lambda wewnątrz mapy () w następujący sposób:

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

lub w python3, zamiast tego musisz użyć rozumienia listy:

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

To działa. I „e” nie spowodowało błędu, mimo że myDict nie miał klucza „e”.

Marc Maxmeister
źródło
42
To nie zadziała w Pythonie 3, ponieważ mapi przyjaciele są teraz leniwi i zwracają iteratory. Stosowanie w mapprzypadku działań niepożądanych jest ogólnie uważane za złą praktykę; standardowa for ... inpętla byłaby lepsza. Aby uzyskać więcej informacji, zobacz Widoki i iteratory zamiast list .
Greg Krimer,
5
Niezależnie od gustu i stylu ćwiczeń, wyliczenia list powinny nadal działać w Py3 [myDict.pop(i, None) for i in ['a', 'c']], ponieważ stanowią ogólną alternatywę dla map(i filter).
Michael Ekoka
@MichaelEkoka nie powinieneś używać list ze względu na ich skutki uboczne, używaj regularnej for ... inpętli.
Boris
@ Boris Prawdopodobnie masz rację. Moja odpowiedź dotyczy w szczególności używania map(), które często stosuje się ze względu na skutki uboczne. Zalecaną alternatywą w Pythonie jest rozumienie listy, które moim zdaniem jest nadal dość czytelne i poznawczo lekkie jako jednowierszowe (patrz pytanie). Obie konstrukcje, użyte tylko ze względu na skutki uboczne, w rzeczywistości dają bezużyteczną listę, która może być nieefektywna. Począwszy od Python3, nie znam wbudowanej funkcji, która może bezpiecznie i elegancko iterować przez wyrażenie generatora, bez kosztownego produktu ubocznego, np loop(d.pop(k) for k in ['a', 'b']).
Michael Ekoka,
Cieszę się, że moja najbardziej uprzywilejowana odpowiedź zawiera hacki, których nigdy bym nie użyła. Zrozumienie listy (opcja 3) jest moim zdaniem najmniej złym podejściem. Użyj tego.
Marc Maxmeister,
19

Możesz użyć słownika, aby utworzyć nowy słownik z usuniętym kluczem:

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

Możesz usunąć według warunków. Brak błędu, jeśli keynie istnieje.

Shameem
źródło
13

Używając słowa kluczowego „del”:

del dict[key]
Sarthak Gupta
źródło
7

Możemy usunąć klucz ze słownika Python, stosując następujące metody.

Za pomocą delsłowa kluczowego; jest to prawie takie samo podejście jak ty -

 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}

Lub

Możemy wykonać następujące czynności:

Należy jednak pamiętać, że w tym procesie nie usuwa on żadnego klucza ze słownika, a nie wyklucza określony klucz ze słownika. Ponadto zauważyłem, że zwrócił słownik, który nie został zamówiony tak samo jak myDict.

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

Jeśli uruchomimy go w powłoce, wykona on coś w stylu {'five': 500, 'four': 400, 'three': 300, 'two': 200}- zauważ, że nie jest to ta sama kolejność co myDict. Ponownie, jeśli spróbujemy wydrukować myDict, możemy zobaczyć wszystkie klucze, w tym te, które wykluczyliśmy ze słownika dzięki temu podejściu. Możemy jednak utworzyć nowy słownik, przypisując następującą instrukcję do zmiennej:

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

Teraz, jeśli spróbujemy go wydrukować, będzie on zgodny z kolejnością nadrzędną:

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

Lub

Przy użyciu pop()metody

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

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

Różnica między deli poppolega na tym, że za pomocą pop()metody możemy w razie potrzeby przechowywać wartość klucza , na przykład:

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

Rozwiąż istotę do wykorzystania w przyszłości, jeśli okaże się to przydatne.

iNet
źródło
1
Nie if myDict.get('one')sprawdzaj, czy klucz jest obecny! Nie udaje się, jeśli myDict [„one”] ma wartość falsey. Ponadto dyktaty nie mają właściwej kolejności, więc nie ma sensu o tym wspominać.
Rob
Dykt @Rob są uporządkowane według kolejności wstawiania zaczynającej się od CPython 3.6 i wszystkich innych implementacji Python zaczynających się od 3.7.
Boris,
4

Możesz użyć obsługi wyjątków, jeśli chcesz być bardzo szczegółowy:

try: 
    del dict[key]

except KeyError: pass

Jest to jednak wolniejsze niż pop()metoda, jeśli klucz nie istnieje.

my_dict.pop('key', None)

Dla kilku klawiszy nie będzie to miało znaczenia, ale jeśli robisz to wielokrotnie, to druga metoda jest lepszym rozwiązaniem.

Najszybsze podejście to:

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

Ale ta metoda jest niebezpieczna, ponieważ jeśli 'key'zostanie usunięta między dwiema liniami, KeyErrorzostanie podniesiona a.

Alec Alameddine
źródło
1

Wolę niezmienną wersję

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}
CervEd
źródło
1

Innym sposobem jest użycie przedmiotów () + rozumienie dykt

items () w połączeniu ze zrozumieniem dict może również pomóc nam w realizacji zadania usuwania pary klucz-wartość, ale ma tę wadę, że nie jest techniką dyktowania w miejscu. Właściwie nowy dykt, jeśli zostanie utworzony, z wyjątkiem klucza, którego nie chcemy dołączać.

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)) 

Wynik:

dictionary before performing remove is : {'sai': 22, 'kiran': 21, 'vinod': 21, 'sangam': 21}
dictionary after remove is : {'sai': 22, 'kiran': 21, 'sangam': 21}
Sai Kiran Sangam
źródło
0

Pojedynczy filtr na kluczu

  • zwróć „klucz” i usuń go z my_dict, jeśli „my” istnieje w my_dict
  • return None, jeśli „klucz” nie istnieje w my_dict

to się zmieni my_dictw miejscu (zmienne)

my_dict.pop('key', None)

Wiele filtrów na klawiszach

wygeneruj nowy dykt (niezmienny)

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()
            )
    )
)
ZenG
źródło