it-swarm.com.de

Löschen Sie ein Element aus einem Wörterbuch

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 (d. H. Das Original nicht zu ändern)?

1184
richzilla

Die del -Anweisung entfernt ein Element:

del d[key]

Dies mutiert jedoch das vorhandene Wörterbuch, sodass sich der Inhalt des Wörterbuchs für alle anderen ändert, die einen Verweis auf dieselbe Instanz haben. Erstellen Sie eine Kopie des Wörterbuchs, um ein neues Wörterbuch zurückzugeben:

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

Der Konstruktor dict() erstellt eine flache Kopie . Eine ausführliche Kopie finden Sie im copy -Modul .


Beachten Sie, dass für jedes Diktat del/assign/etc eine Kopie erstellt wird. bedeutet, dass Sie von konstanter Zeit zu linearer Zeit wechseln und auch linearen Raum verwenden. Für kleine Dikte ist dies kein Problem. Wenn Sie jedoch viele Kopien von großen Dikten erstellen möchten, möchten Sie wahrscheinlich eine andere Datenstruktur, wie z. B. ein HAMT (wie in diese Antwort ) beschrieben.

1521
Greg Hewgill

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.

205
Crystal

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 erstellen, indem Sie die Schlüssel aus dem alten Wörterbuch verwenden, ohne den angegebenen Schlüssel einzuschließen.

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

Die del-Anweisung ist das, wonach Sie suchen. Wenn Sie ein Wörterbuch mit dem Namen foo und dem Schlüssel 'bar' haben, können Sie 'bar' wie folgt aus foo löschen:

_del foo['bar']
_

Beachten Sie, dass dadurch das Wörterbuch, mit dem gearbeitet wird, dauerhaft geändert wird. Wenn Sie das ursprüngliche Wörterbuch behalten möchten, müssen Sie zuvor eine Kopie erstellen:

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

Der Aufruf dict erstellt eine flache Kopie. Wenn Sie eine ausführliche Kopie wünschen, verwenden Sie copy.deepcopy .

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

_def minus_key(key, dictionary):
    shallow_copy = dict(dictionary)
    del shallow_copy[key]
    return shallow_copy
_
52
arussell84

Es gibt viele nette Antworten, aber ich möchte eine Sache hervorheben.

Sie können sowohl die dict.pop() -Methode als auch eine allgemeinere del -Anweisung verwenden, um Elemente aus einem Wörterbuch zu entfernen. Beide mutieren das ursprüngliche Wörterbuch, sodass Sie eine Kopie erstellen müssen (siehe Details unten).

Und beide werfen ein KeyError auf, wenn der Schlüssel, den Sie ihnen zur Verfügung stellen, nicht im Wörterbuch 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:

durch Erfassen der Ausnahme:

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 Ausführen 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() gibt es auch eine viel präzisere Möglichkeit - geben Sie den Standardrückgabewert an:

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

Sofern Sie nicht pop() verwenden, um den Wert eines zu entfernenden Schlüssels zu ermitteln, können Sie alles angeben, was nicht erforderlich ist. None. Obwohl es sein kann, dass die Verwendung von del mit in -Prüfung etwas schneller ist , da pop() eine Funktion mit eigenen Komplikationen ist, die Overhead verursachen. Normalerweise ist dies nicht der Fall, daher ist pop() mit dem Standardwert gut genug.


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

Einige andere Leute hier schlagen vor, eine vollständige (tiefe) Kopie mit copy.deepcopy() zu erstellen. Dies könnte ein Overkill sein, eine "normale" (flache) Kopie mit . copy.copy() oder dict.copy() könnte ausreichen. Das Wörterbuch enthält einen Verweis 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, auf das verwiesen wird. Das Objekt selbst kann später automatisch vom Garbage Collector entfernt werden, wenn keine anderen Referenzen dafür im Speicher vorhanden sind. Das Erstellen einer tiefen Kopie erfordert mehr Berechnungen als das Erstellen einer flachen Kopie. Dadurch wird die Codeleistung verringert, indem die Kopie erstellt, Speicher verschwendet und dem GC mehr Arbeit zur Verfügung gestellt wird. Manchmal reicht eine flache Kopie aus.

Wenn Sie jedoch veränderbare Objekte als Wörterbuchwerte haben und diese später im zurückgegebenen Wörterbuch ohne den Schlüssel ändern möchten, müssen Sie eine umfangreiche 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}
45
Nikita
d = {1: 2, '2': 3, 5: 7}
del d[5]
print 'd = ', d

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

19
satels

… Wie kann ich ein Objekt aus einem Wörterbuch löschen, um eine Kopie zurückzugeben (d. H. Das Original nicht zu ändern)?

Ein dict ist die falsche Datenstruktur, die dafür verwendet wird.

Sicher, das Kopieren des Diktats und das Poppen von der Kopie funktioniert, und das Erstellen eines neuen Diktats mit einem Verständnis, aber all das Kopieren braucht Zeit - Sie haben eine Operation mit konstanter Zeit durch eine Operation mit linearer Zeit ersetzt. Und all diese lebendigen Kopien belegen gleichzeitig Speicherplatz - linearer Speicherplatz pro Kopie.

Andere Datenstrukturen, wie Hash-Array-zugeordnete Versuche , sind für genau diese Art von Anwendungsfall konzipiert: Das Hinzufügen oder Entfernen eines Elements gibt eine Kopie in logarithmischer Zeit, wobei der größte Teil seines Speichers mit dem gemeinsam genutzt wird 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 mit dict identisch machen können, unterscheidet sich die "mutierende" API offensichtlich. Und vor allem sind in Python keine HAMT-Batterien enthalten.2

Die pyrsistent Bibliothek ist eine ziemlich solide Implementierung von HAMT-basierten Diktier-Ersetzungen (und verschiedenen anderen Typen) für Python. Es hat sogar eine raffinierte Evolver-API , um vorhandenen mutierenden Code so reibungslos wie möglich in persistenten Code zu portieren. Wenn Sie jedoch explizit Kopien zurückgeben möchten, anstatt sie zu mutieren, verwenden Sie dies einfach so:

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

Das d3 = d1.remove('a') ist genau das, was die Frage verlangt.

Wenn in dict veränderbare Datenstrukturen wie list und pmap eingebettet sind, treten weiterhin Aliasing-Probleme auf. Sie können dies nur beheben, indem Sie pmaps und pvectors vollständig unveränderlich machen.


1. HAMTs sind auch in Sprachen wie Scala, Clojure und Haskell populär geworden, weil sie sehr gut mit sperrenfreiem Programmieren und Software-Transaktionsspeicher spielen, aber keines davon ist in Python sehr relevant.

2. Tatsächlich gibt es is ein HAMT in der stdlib, das bei der Implementierung von contextvars verwendet wird. Das zuvor zurückgezogene PEP erklärt, warum. Dies ist jedoch ein verstecktes Implementierungsdetail der Bibliothek, kein öffentlicher Sammlungstyp.

13
abarnert

Rufen Sie einfach del d ['key'] auf.

In der Produktion ist es jedoch immer ratsam, zu überprüfen, ob in d ein Schlüssel vorhanden ist.

if 'key' in d:
    del d['key']
13
Khanh Hua

Nein, es gibt keinen anderen Weg als

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

Oft ist es jedoch keine gute Idee, Kopien von nur geringfügig veränderten Wörterbüchern zu erstellen, da dies zu einem vergleichsweise hohen Speicherbedarf führt. In der Regel ist es besser, das alte Wörterbuch zu protokollieren (falls erforderlich) und es dann zu ändern.

7
phihag
# mutate/remove with a default
ret_val = body.pop('key', 5)
# no mutation with a default
ret_val = body.get('key', 5)
6
daino3

Hier ein Designansatz auf höchstem Niveau:

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 übergebe das Wörterbuch und den gewünschten Schlüssel an meine Funktion, überprüfe, ob es sich um ein Wörterbuch handelt und ob der Schlüssel in Ordnung ist, und wenn beides vorhanden ist, entferne ich den Wert aus dem Wörterbuch und drucke die Reste aus.

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

Ich hoffe, das hilft!

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 führt zu keiner Fehlerbehandlung. Es wird davon ausgegangen, dass der Schlüssel im Diktat enthalten ist. Sie sollten dies zuerst überprüfen und raise, wenn dies nicht der Fall ist

5
tMC

Das folgende Code-Snippet wird Ihnen definitiv helfen. Ich habe Kommentare in jede Zeile eingefügt, die Ihnen helfen, den Code zu verstehen.

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 du kannst auch dict.pop () benutzen

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}
3
Mayur Agarwal

Hier ist eine weitere Variante 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 Methode zum Entfernen von Schlüsseln mit leeren Zeichenfolgen aus einem Diktat

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

Mit dem folgenden Code wird eine Kopie von dict species erstellt und Elemente gelöscht, die nicht in trans_HI enthalten sind.

trans_HI=['1025','1215']
for transition in species['HI'].copy().keys():
    if transition not in trans_HI:
        species['HI'].pop(transition)
0
Schlator