Frage

Gibt es eine Möglichkeit, ein Element aus einem Wörterbuch in Python zu löschen?

Wie kann ich außerdem ein Element aus einem Wörterbuch löschen, um eine Kopie zurückzugeben (dh das Original nicht ändern)?

War es hilfreich?

Lösung

Das del Aussage Entfernt ein Element:

del d[key]

Dies mutiert jedoch das bestehende Wörterbuch, sodass der Inhalt des Wörterbuchs für alle anderen ändert, die einen Hinweis auf dieselbe Instanz haben. Zurückkehren a Neu Wörterbuch, machen Sie eine Kopie des Wörterbuchs:

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

Das dict() Konstruktor macht a flache Kopie. Um eine tiefe Kopie zu machen, siehe die copy Modul.


Beachten Sie, dass ein Kopie für jedes Dikte erstellt wird del/Zuordnung/etc. bedeutet, dass Sie von ständiger Zeit zu linearer Zeit gehen und auch lineare Raum nutzen. Für kleine Diktate ist dies kein Problem. Wenn Sie jedoch vorhaben, viele Kopien großer Diktate zu erstellen, möchten Sie wahrscheinlich eine andere Datenstruktur, wie eine HAMT (wie in beschrieben in Diese Antwort).

Andere Tipps

pop mutiert das Wörterbuch.

 >>>lol = {"hello":"gdbye"}
 >>>lol.pop("hello")
    'gdbye'
 >>> lol
     {}

Wenn Sie das Original behalten möchten, können Sie es einfach kopieren.

Ich denke, Ihre Lösung ist der beste Weg, dies zu tun. Wenn Sie jedoch eine andere Lösung wünschen, können Sie ein neues Wörterbuch mit den Schlüssel aus dem alten Wörterbuch erstellen, ohne Ihren angegebenen Schlüssel einzuschließen, wie folgt:

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

Das Del Anweisung ist was Sie suchen. Wenn Sie ein Wörterbuch namens Foo mit einem Schlüssel namens "Bar" haben, können Sie "Bar" von Foo wie folgt löschen:

del foo['bar']

Beachten Sie, dass dies das Wörterbuch dauerhaft verändert. Wenn Sie das ursprüngliche Wörterbuch behalten möchten, müssen Sie vorher eine Kopie erstellen:

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

Das dict Anruf macht eine flache Kopie. Wenn Sie eine tiefe Kopie wünschen, verwenden Sie copy.deepcopy.

Hier ist eine Methode, die Sie für Ihre Bequemlichkeit kopieren und einfügen können:

def minus_key(key, dictionary):
    shallow_copy = dict(dictionary)
    del shallow_copy[key]
    return shallow_copy

Es gibt viele schöne Antworten, aber ich möchte eine Sache betonen.

Sie können beide verwenden dict.pop() Methode und eine generischere del Aussage Gegenstände aus einem Wörterbuch entfernen. Beide mutieren das ursprüngliche Wörterbuch, sodass Sie eine Kopie erstellen müssen (siehe Details unten).

Und beide werden a erheben KeyError Wenn der Schlüssel, den Sie ihnen zur Verfügung stellen, im Wörterbuch nicht vorhanden ist:

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

und

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

Sie müssen sich darum kümmern:

Indem Sie die Ausnahme erfassen:

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)

und

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)

Durch die Ausführung einer Überprüfung:

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

und

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

aber mit pop() Es gibt auch einen viel prägnanteren Weg - geben Sie den Standard -Rückgabewert an:

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

Es sei denn, Sie verwenden pop() Um den Wert eines Schlüssels zu erhalten, das entfernt wird, können Sie alles bereitstellen, nicht notwendig None. Obwohl es so sein könnte, dass es verwendet wird del mit in prüfen ist leicht schneller wegen pop() Eine Funktion mit eigenen Komplikationen zu sein, die Overhead verursachen. Normalerweise ist es nicht der Fall, also pop() mit Standardwert ist gut genug.


Was die Hauptfrage betrifft, müssen Sie eine Kopie Ihres Wörterbuchs erstellen, um das ursprüngliche Wörterbuch zu retten und eine neue zu haben, ohne dass der Schlüssel entfernt wird.

Einige andere Leute hier empfehlen eine vollständige (tiefe) Kopie mit copy.deepcopy(), was ein Overkill sein könnte, eine "normale" (flache) Kopie, verwendet copy.copy() oder dict.copy(), könnte genug sein. Das Wörterbuch führt einen Hinweis auf das Objekt als Wert für einen Schlüssel. Wenn Sie also einen Schlüssel aus einem Wörterbuch entfernen, wird diese Referenz entfernt, nicht das Objekt, das verwiesen wird. Das Objekt selbst kann später automatisch vom Müllsammler entfernt werden, wenn es keine anderen Referenzen dafür im Speicher gibt. Eine tiefe Kopie erfordert mehr Berechnungen im Vergleich zur flachen Kopie. Daher verringert sie die Code -Leistung, indem die Kopie erstellt, Speicher verschwendet und dem GC mehr Arbeit liefert. Manchmal reicht flache Kopien aus.

Wenn Sie jedoch veränderliche Objekte als Wörterbuchwerte haben und planen, sie später im zurückgegebenen Wörterbuch ohne den Schlüssel zu ändern, müssen Sie eine tiefe Kopie erstellen.

Mit flacher Kopie:

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}

Mit tiefer Kopie:

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}
d = {1: 2, '2': 3, 5: 7}
del d[5]
print 'd = ', d

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

… Wie kann ich ein Element aus einem Wörterbuch löschen, um eine Kopie zurückzugeben (dh nicht das Original ändern)?

EIN dict Ist dafür die falsche Datenstruktur.

Sicher, das Kopieren des Dikts und das Aussteigen aus den Kopien. Und all diese Kopien, die auf einmal lebendig sind - linart Platz pro Kopie.

Andere Datenstrukturen wie Hash -Array zugeordneten Versuche, sind für genau diese Art von Anwendungsfall ausgelegt: Hinzufügen oder Entfernen eines Elements gibt eine Kopie zurück In der logarithmischen Zeit teilen Sie den größten Teil seines Speichers mit dem Original.1

Natürlich gibt es einige Nachteile. Die Leistung ist eher logarithmisch als konstant (obwohl mit einer großen Basis, normalerweise 32-128). Und während Sie die nicht mutierende API identisch machen können dict, Die "mutierende" API ist offensichtlich anders. Und vor allem gibt es keine Hamt -Batterien in Python.2

Das pyrsistent Die Bibliothek ist eine ziemlich solide Implementierung von HAMT-basierten Diktatverordnungen (und verschiedenen anderen Typen) für Python. Es hat sogar eine raffinierte Evolver API Für die Portierung des vorhandenen Mutationscodes auf persistierende Code so reibungslos wie möglich. Wenn Sie jedoch explizit über die Rückgabe von Kopien statt mutieren möchten, verwenden Sie es einfach wie folgt:

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

Dass d3 = d1.remove('a') Ist genau das, was die Frage stellt.

Wenn Sie veränderliche Datenstrukturen haben wie dict und list eingebettet in die pmap, Sie werden immer noch Aliasing -Probleme haben - Sie können das nur beheben pmaps und pvectors.


1. Hamts sind auch in Sprachen wie Scala, Clojure, Haskell populär geworden, weil sie sehr gut mit schlossfreiem Programmier- und Software-Transaktionsgedächtnis spielen, aber keiner davon ist in Python sehr relevant.

2. In der Tat dort ist eine HAMT in der STDLIB, die bei der Implementierung von verwendet wird contextvars. Der früher zurückgezogene Pep erklärt, warum. Dies ist jedoch ein verstecktes Implementierungsdetail der Bibliothek, kein öffentlicher Sammlungstyp.

Rufen Sie einfach del d ['Key'] an.

In der Produktion ist es jedoch immer eine gute Praxis zu überprüfen, ob in d 'Schlüssel' vorhanden ist.

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

Nein, es gibt keinen anderen Weg als

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

Das Erstellen von Kopien von nur geringfügig veränderten Wörterbüchern ist jedoch wahrscheinlich keine gute Idee, da dies zu vergleichsweise großen Gedächtnisanforderungen führt. Es ist normalerweise besser, das alte Wörterbuch zu protokollieren (falls erforderlich) und es dann zu ändern.

# mutate/remove with a default
ret_val = body.pop('key', 5)
# no mutation with a default
ret_val = body.get('key', 5)
>>> def delete_key(dict, key):
...     del dict[key]
...     return dict
... 
>>> test_dict = {'one': 1, 'two' : 2}
>>> print delete_key(test_dict, 'two')
{'one': 1}
>>>

Dies macht keine Fehlerbehandlung, sondern wird davon ausgegangen raise Wenn es nicht ist

Hier ein Top -Level -Design -Ansatz:

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

Ich übertrage das Wörterbuch und den Schlüssel, den ich möchte, überprüft, ob es sich um ein Wörterbuch handelt. Wenn der Schlüssel in Ordnung ist und wenn beide existieren, wird der Wert aus dem Wörterbuch entfernt und druckt die Linken aus.

Ausgabe: {'B': 55, 'A': 34}

Ich hoffe, das hilft!

Unter dem Code -Snippet hilft Ihnen auf jeden Fall. Ich habe in jeder Zeile Kommentare hinzugefügt, die Ihnen beim Verständnis des Codes helfen.

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

oder Sie können auch dict.pop () verwenden

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

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

oder der bessere Ansatz ist

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}

Hier ist eine weitere Variation mit Listenverständnis:

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

Der Ansatz basiert auf einer Antwort aus diesem Beitrag:Effiziente Möglichkeit, Tasten mit leeren Saiten aus einem Dikten zu entfernen

    species = {'HI': {'1': (1215.671, 0.41600000000000004),
  '10': (919.351, 0.0012),
  '1025': (1025.722, 0.0791),
  '11': (918.129, 0.0009199999999999999),
  '12': (917.181, 0.000723),
  '1215': (1215.671, 0.41600000000000004),
  '13': (916.429, 0.0005769999999999999),
  '14': (915.824, 0.000468),
  '15': (915.329, 0.00038500000000000003),
 'CII': {'1036': (1036.3367, 0.11900000000000001), '1334': (1334.532, 0.129)}}

Der folgende Code erstellt eine Kopie von DICT species und Artikel löschen, die nicht in sind trans_HI

trans_HI=['1025','1215']
for transition in species['HI'].copy().keys():
    if transition not in trans_HI:
        species['HI'].pop(transition)
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top