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.


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.


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


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

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


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.



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ąż tę istotę do wykorzystania w przyszłości, jeśli okaże się to przydatne.


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.


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}

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}

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()
            )
    )
)
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.