Usuwanie elementu ze słownika

Czy istnieje sposób na usunięcie elementu ze słownika w Pythonie?

DODATKOWO, Jak mogę usunąć element ze słownika, aby zwrócić kopię (tzn. nie modyfikować oryginału)?

Author: coldspeed, 2011-05-01

14 answers

The del Instrukcja usuwa element:

del d[key]

Jednakże powoduje to mutację istniejącego słownika, więc zawartość słownika zmienia się dla każdego, kto ma odniesienie do tej samej instancji. Aby zwrócić Nowy słownik , wykonaj kopię słownika:

def removekey(d, key):
    r = dict(d)
    del r[key]
    return r

Konstruktor dict() tworzypłytką kopię . Aby zrobić głęboką kopię, zobacz copy moduł .


Zauważ, że tworzenie kopii dla każdego dict del/assignment / etc. oznacza przejście od czasu stałego do czasu liniowego, a także użycie przestrzeni liniowej. Dla małych dictów nie jest to problem. Ale jeśli planujesz zrobić wiele kopii dużych dictów, prawdopodobnie potrzebujesz innej struktury danych, jak HAMT(jak opisano w ta odpowiedź ).

 1248
Author: Greg Hewgill,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-15 01:27:47

pop mutuje słownik.

 >>>lol = {"hello":"gdbye"}
 >>>lol.pop("hello")
    'gdbye'
 >>> lol
     {}
Jeśli chcesz zachować oryginał, możesz go skopiować.
 145
Author: Crystal,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-02-14 11:08:00

Myślę, że Twoje rozwiązanie jest najlepszym sposobem, aby to zrobić. Ale jeśli chcesz innego rozwiązania, możesz utworzyć nowy słownik za pomocą kluczy ze starego słownika bez włączania określonego klucza, jak to:

>>> a
{0: 'zero', 1: 'one', 2: 'two', 3: 'three'}
>>> {i:a[i] for i in a if i!=0}
{1: 'one', 2: 'two', 3: 'three'}
 56
Author: utdemir,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-04-30 21:26:40

Oświadczenie del jest tym, czego szukasz. Jeśli masz Słownik o nazwie foo z kluczem o nazwie 'bar', możesz usunąć 'bar' z foo w następujący sposób:

del foo['bar']

Zauważ, że to trwale modyfikuje słownik, na którym jest operowany. Jeśli chcesz zachować oryginalny słownik, musisz wcześniej utworzyć kopię:

>>> foo = {'bar': 'baz'}
>>> fu = dict(foo)
>>> del foo['bar']
>>> print foo
{}
>>> print fu
{'bar': 'baz'}

The dict call robi płytką kopię. Jeśli chcesz mieć głęboką kopię, użyj copy.deepcopy.

Oto metoda, którą możesz skopiować & wklej, dla Twojej wygody:

def minus_key(key, dictionary):
    shallow_copy = dict(dictionary)
    del shallow_copy[key]
    return shallow_copy
 47
Author: arussell84,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-30 14:27:40

Jest wiele ładnych odpowiedzi, ale chcę podkreślić jedną rzecz.

Możesz użyć obu dict.pop() metoda i bardziej ogólny del oświadczenie , aby usunąć elementy ze słownika. Oba mutują oryginalny Słownik, więc musisz zrobić kopię(zobacz szczegóły poniżej).

I oboje podniosą KeyError jeśli klucz, który im podajesz, nie jest obecny w słowniku:

key_to_remove = "c"
d = {"a": 1, "b": 2}
del d[key_to_remove]  # Raises `KeyError: 'c'`

I

key_to_remove = "c"
d = {"a": 1, "b": 2}
d.pop(key_to_remove)  # Raises `KeyError: 'c'`

Ty trzeba się tym zająć:

Przez przechwycenie wyjątku:

key_to_remove = "c"
d = {"a": 1, "b": 2}
try:
    del d[key_to_remove]
except KeyError as ex:
    print("No such key: '%s'" % ex.message)

I

key_to_remove = "c"
d = {"a": 1, "b": 2}
try:
    d.pop(key_to_remove)
except KeyError as ex:
    print("No such key: '%s'" % ex.message)

Wykonując kontrolę:

key_to_remove = "c"
d = {"a": 1, "b": 2}
if key_to_remove in d:
    del d[key_to_remove]

I

key_to_remove = "c"
d = {"a": 1, "b": 2}
if key_to_remove in d:
    d.pop(key_to_remove)

Ale z pop() istnieje również znacznie bardziej zwięzły sposób-podaj domyślną wartość zwracaną:

key_to_remove = "c"
d = {"a": 1, "b": 2}
d.pop(key_to_remove, None)  # No `KeyError` here

Jeśli nie użyjesz pop(), aby uzyskać wartość usuwanego klucza, możesz podać cokolwiek, co nie jest konieczne None. Choć może być tak, że użycie del z in check jest nieco szybciej ze względu na to, że pop() jest funkcją z własnymi komplikacjami powodującymi nadmiarowość. Zazwyczaj tak nie jest, więc {[12] } z wartością domyślną jest wystarczająco dobra.


Jeśli chodzi o główne pytanie, musisz zrobić kopię swojego słownika, aby zapisać oryginalny słownik i mieć nowy bez usuwania klucza.

Niektórzy tutaj sugerują zrobienie pełnej (głębokiej) kopii z copy.deepcopy(), co może być przesadą, "normalnym" (płytkim) Kopiuj, używając copy.copy() lub dict.copy(), może wystarczy. Słownik zachowuje odniesienie do obiektu jako wartość klucza. Więc kiedy usuniesz klucz ze słownika, to odniesienie zostanie usunięte, a nie obiekt, do którego się odwołuje. Sam obiekt może zostać później automatycznie usunięty przez garbage collector, jeśli w pamięci nie ma innych odniesień do niego. Wykonanie głębokiej kopii wymaga więcej obliczeń w porównaniu z płytką kopią, więc zmniejsza wydajność kodu poprzez wykonanie kopiowanie, marnowanie pamięci i dostarczanie większej ilości pracy do GC, czasem wystarczy płytka Kopia.

Jeśli jednak jako wartości słownika masz zmienne obiekty i planujesz je później zmodyfikować w zwracanym słowniku bez klucza, musisz wykonać głęboką kopię.

Z płytką kopią:

def get_dict_wo_key(dictionary, key):
    """Returns a **shallow** copy of the dictionary without a key."""
    _dict = dictionary.copy()
    _dict.pop(key, None)
    return _dict


d = {"a": [1, 2, 3], "b": 2, "c": 3}
key_to_remove = "c"

new_d = get_dict_wo_key(d, key_to_remove)
print(d)  # {"a": [1, 2, 3], "b": 2, "c": 3}
print(new_d)  # {"a": [1, 2, 3], "b": 2}
new_d["a"].append(100)
print(d)  # {"a": [1, 2, 3, 100], "b": 2, "c": 3}
print(new_d)  # {"a": [1, 2, 3, 100], "b": 2}
new_d["b"] = 2222
print(d)  # {"a": [1, 2, 3, 100], "b": 2, "c": 3}
print(new_d)  # {"a": [1, 2, 3, 100], "b": 2222}

Z głęboką kopią:

from copy import deepcopy


def get_dict_wo_key(dictionary, key):
    """Returns a **deep** copy of the dictionary without a key."""
    _dict = deepcopy(dictionary)
    _dict.pop(key, None)
    return _dict


d = {"a": [1, 2, 3], "b": 2, "c": 3}
key_to_remove = "c"

new_d = get_dict_wo_key(d, key_to_remove)
print(d)  # {"a": [1, 2, 3], "b": 2, "c": 3}
print(new_d)  # {"a": [1, 2, 3], "b": 2}
new_d["a"].append(100)
print(d)  # {"a": [1, 2, 3], "b": 2, "c": 3}
print(new_d)  # {"a": [1, 2, 3, 100], "b": 2}
new_d["b"] = 2222
print(d)  # {"a": [1, 2, 3], "b": 2, "c": 3}
print(new_d)  # {"a": [1, 2, 3, 100], "b": 2222}
 22
Author: Nikita,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-01-23 05:15:18
d = {1: 2, '2': 3, 5: 7}
del d[5]
print 'd = ', d

Wynik: d = {1: 2, '2': 3}

 16
Author: satels,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-04-30 21:24:48

Po prostu wywołaj del D ['klucz'].

Jednak w produkcji zawsze dobrą praktyką jest sprawdzanie, czy "klucz" istnieje w d.

if 'key' in d:
    del d['key']
 12
Author: Khanh Hua,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-03-02 13:39:10

Nie, Nie ma innej drogi niż

def dictMinus(dct, val):
   copy = dct.copy()
   del copy[val]
   return copy

Jednak często tworzenie kopii tylko nieznacznie zmienionych słowników prawdopodobnie nie jest dobrym pomysłem, ponieważ spowoduje to stosunkowo duże zapotrzebowanie na pamięć. Zwykle lepiej jest zalogować się do starego słownika(jeśli jest to konieczne), a następnie zmodyfikować go.

 6
Author: phihag,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-04-30 21:27:32
>>> def delete_key(dict, key):
...     del dict[key]
...     return dict
... 
>>> test_dict = {'one': 1, 'two' : 2}
>>> print delete_key(test_dict, 'two')
{'one': 1}
>>>

To nie robi żadnej obsługi błędów, zakłada, że klucz jest w dict, możesz chcieć to sprawdzić najpierw i raise jeśli nie

 5
Author: tMC,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-04-30 21:26:25

... Jak mogę usunąć element ze słownika, aby zwrócić kopię (tzn. nie modyfikować oryginału)?

A {[1] } jest niewłaściwą strukturą danych do tego celu.

Jasne, kopiowanie dict i wyskakiwanie z kopii działa, podobnie jak budowanie nowego dict ze zrozumieniem, ale wszystko to kopiowanie wymaga czasu-zastąpiłeś operację czasową stałą na czas liniowy. Wszystkie te kopie naraz zajmują przestrzeń liniową na jedną kopię.

Inne struktury danych, takie jak hash array mapped tries , są zaprojektowane do tego typu przypadków użycia: dodanie lub usunięcie elementu zwraca kopię w czasie logarytmicznym, dzieląc większość jego przechowywania z oryginalnym.1

Oczywiście są pewne wady. Wydajność jest logarytmiczna, a nie stała (choć z dużą podstawą, Zwykle 32-128). I chociaż można uczynić API niemutujące identycznym z dict, API" mutujące " jest oczywiście inne. A przede wszystkim nie ma baterii HAMT w zestawie z Pythonem.2

The pyrsistent Biblioteka jest dość solidną implementacją opartych na HAMT dict-replacements (i różnych innych typów) dla Pythona. Posiada nawet sprytne evolver API do przenoszenia istniejącego mutującego kodu na trwały kod tak płynnie, jak to możliwe. Ale jeśli chcesz być szczery o zwracaniu kopii, a nie mutacji, po prostu użyj tego w następujący sposób:

>>> from pyrsistent import m
>>> d1 = m(a=1, b=2)
>>> d2 = d1.set('c', 3)
>>> d3 = d1.remove('a')
>>> d1
pmap({'a': 1, 'b': 2})
>>> d2
pmap({'c': 3, 'a': 1, 'b': 2})
>>> d3
pmap({'b': 2})

That d3 = d1.remove('a') is exactly what pytanie zadaje pytanie.

Jeśli masz zmienne struktury danych, takie jak dict i list osadzone w pmap, nadal będziesz mieć problemy z aliasingiem-możesz to naprawić tylko, przechodząc niezmiennie w dół, osadzając pmap s I pvector s.


1. HAMTs stały się również popularne w językach takich jak Scala, Clojure, Haskell, ponieważ grają bardzo ładnie z programowaniem bez blokady i pamięcią transakcyjną oprogramowania, ale żaden z nich nie jest bardzo istotny w Python.

2. W rzeczywistości istnieje HAMT w stdlib, używany w implementacji contextvars. wcześniej wycofany PEP wyjaśnia dlaczego. ale jest to ukryty szczegół implementacji biblioteki, a nie Typ kolekcji publicznej.

 5
Author: abarnert,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-15 01:33:06

Tutaj podejście do projektowania na najwyższym poziomie:

def eraseElement(d,k):
    if isinstance(d, dict):
        if k in d:
            d.pop(k)
            print(d)
        else:
            print("Cannot find matching key")
    else:
        print("Not able to delete")


exp = {'A':34, 'B':55, 'C':87}
eraseElement(exp, 'C')

Przekazuję słownik i klucz, który chcę do mojej funkcji, sprawdza, czy jest to słownik i czy klucz jest w porządku, a jeśli oba istnieją, usuwa wartość ze słownika i wypisuje lewe przejścia.

Wyjście: {'B': 55, 'A': 34}

Mam nadzieję, że to pomoże!
 4
Author: Bishop,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-08-15 15:50:44

Nice one-liner, aby sprawdzić, czy klucz jest obecny, usunąć go, zwrócić wartość, lub domyślne:

ret_val = ('key' in body and body.pop('key')) or 5
 3
Author: daino3,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-08-05 20:40:53

Poniższy fragment kodu zdecydowanie ci pomoże, dodałem komentarze w każdej linii, które pomogą Ci w zrozumieniu kodu.

def execute():
   dic = {'a':1,'b':2}
   dic2 = remove_key_from_dict(dic, 'b')  
   print(dict2)           # {'a': 1}
   print(dict)            # {'a':1,'b':2}

def remove_key_from_dict(dictionary_to_use, key_to_delete):
   copy_of_dict = dict(dictionary_to_use)     # creating clone/copy of the dictionary
   if key_to_delete in copy_of_dict :         # checking given key is present in the dictionary
       del copy_of_dict [key_to_delete]       # deleting the key from the dictionary 
   return copy_of_dict                        # returning the final dictionary

Lub możesz również użyć dict.pop ()

d = {"a": 1, "b": 2}

res = d.pop("c")  # No `KeyError` here
print (res)       # this line will not execute

Or the better approach is

res = d.pop("c", "key not found")
print (res)   # key not found
print (d)     # {"a": 1, "b": 2}

res = d.pop("b", "key not found")
print (res)   # 2
print (d)     # {"a": 1}
 3
Author: Mayur Agarwal,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-09-30 20:10:01

Oto kolejna odmiana wykorzystująca rozumienie listy:

original_d = {'a': None, 'b': 'Some'}
d = dict((k,v) for k, v in original_d.iteritems() if v)
# result should be {'b': 'Some'}

Podejście opiera się na odpowiedzi z tego postu: skuteczny sposób usuwania kluczy z pustymi łańcuchami z dict

 1
Author: BigBlueHat,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:18:24