Gibt es eine Möglichkeit, ein Element in Python aus einem Wörterbuch 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 zu ändern)?
python
dictionary
del
Richzilla
quelle
quelle
pop
Methode ändert das Wörterbuch in-place . Daher ändert es den Verweis auf das Wörterbuch, das vom Aufrufer an die "Hilfsfunktion" übergeben wurde. Die "Hilfsfunktion" muss also nichts zurückgeben, da der ursprüngliche Verweis auf das Wörterbuch im Aufrufer bereits geändert wird. Weisen Sie die Rückgabe vondict.pop()
nichts zu, wenn Sie sie nicht benötigen. EG :do stuff with my_dict; my_dict.pop(my_key, None); do more stuff with my_dict # now doesn't have my_key
. Verwenden Sie,deepcopy(my_dict)
wenn nötig.d.pop()
, habe ich den Titel korrigiert, um die in den Details angegebene Frage zu stellen.d.pop(key)
. Wenn jedoch jemals etwas die flache Kopie ändert, haben Sie ein bekanntes Problem mit dem Aliasing . Es hilft, wenn Sie uns den weiteren Kontext mitteilen. (Ändert irgendetwas anderes jemals die Diktatwerte? Versuchen Sie, eine Liste destruktiv zu durchlaufen? Wenn nicht, was?)Antworten:
Die
del
Anweisung entfernt ein Element:Dies mutiert jedoch das vorhandene Wörterbuch, sodass sich der Inhalt des Wörterbuchs für alle anderen Personen ändert, die auf dieselbe Instanz verweisen. Um ein neues Wörterbuch zurückzugeben, erstellen Sie eine Kopie des Wörterbuchs:
Der
dict()
Konstruktor erstellt eine flache Kopie . Informationen zum Erstellen einer tiefen Kopie finden Sie imcopy
Modul .Beachten Sie, dass Sie für jedes Diktat
del
/ jede Aufgabe / etc. Eine Kopie erstellen . bedeutet, dass Sie von der konstanten Zeit zur linearen Zeit wechseln und auch den linearen Raum verwenden. Für kleine Diktate ist dies kein Problem. Wenn Sie jedoch viele Kopien großer Diktate erstellen möchten, möchten Sie wahrscheinlich eine andere Datenstruktur wie ein HAMT (wie in dieser Antwort beschrieben ).quelle
dict
während Sie es durchlaufen, wird es Ihnen einen Fehler geben:RuntimeError: dictionary changed size during iteration
pop
Methode, die tatsächlich dasselbe tut? Ist es nicht pythonischer? (ist die Methode des Diktats, kein spezielles reserviertes Wort)?pop
mutiert das Wörterbuch.Wenn Sie das Original behalten möchten, können Sie es einfach kopieren.
quelle
pop
Gibt den Wert zurück, der 'popped' war, sodass Sie diesen Wert aus irgendeinem weiteren Grund verwenden können. Wenn es nicht mehr "Pythonic" ist, würde ich sagen, das scheint sicher besser zu sein :). Es ist kein Diktat, aber es funktioniert für beide gleich: github.com/ivanlmj/python-prototypes/blob/master/3.4/…pop
kann mit einem Standardwert versehen werden, der zurückgegeben wird, wenn ein Schlüssel in dict fehlt. Es ist gut, wenn Sie einige Schlüssel entfernen müssen, aber einige davon fehlen möglicherweise.del
würdeKeyError
in einem solchen Fall werfen .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.
quelle
{i:a[i] for i in a if i not in [0, 1, 2]}
Wenn Sie mehrere Elemente entfernen möchten.{k:v for k,v in a.items() if k != 0}
ich denke.**kwargs
,some_function(**{k:v for k,v in some_dict.items() if k not 'some_key'})
Die del-Anweisung ist genau das, wonach Sie suchen. Wenn Sie ein Wörterbuch namens foo mit einem Schlüssel namens "bar" haben, können Sie "bar" wie folgt aus foo löschen:
Beachten Sie, dass dadurch das Wörterbuch, mit dem gearbeitet wird, dauerhaft geändert wird. Wenn Sie das Originalwörterbuch behalten möchten, müssen Sie zuvor eine Kopie erstellen:
Der
dict
Anruf erstellt eine flache Kopie. Wenn Sie eine tiefe Kopie wünschen, verwenden Siecopy.deepcopy
.Hier ist eine Methode, die Sie kopieren und einfügen können:
quelle
>>>
wird in den Python-Beispielen oft verwendet? Ja, Python-Doc enthält viele solcher Dinge. Ein solcher Code ist jedoch für die Kopierpaste nicht geeignet . Ich bin verwirrt ...>>>
ahmt die>>>
. Ja, es ist im REPL-Stil, aber lassen Sie uns ehrlich sprechen: Der einzige Mann hatte dieses Beispiel geschrieben, und 1000 haben es gelesen. Ich denke, es wäre großartig, Beispiele so zu schreiben, dass sie einfach kopiert und ausgeführt werden können. Ich möchte diese spitzen Klammern nicht von Hand entfernen. Oder Zeile für Zeile kopieren. Also verstehe ich nicht: warum diese Winkel noch da sind))) Vielleicht weiß ich etwas nicht?Es gibt viele nette Antworten, aber ich möchte eines hervorheben.
Sie können sowohl eine
dict.pop()
Methode als auch eine allgemeineredel
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 lösen ein aus,
KeyError
wenn der Schlüssel, den Sie ihnen zur Verfügung stellen, nicht im Wörterbuch vorhanden ist:und
Sie müssen sich darum kümmern:
durch Erfassen der Ausnahme:
und
durch eine Prüfung:
und
aber mit
pop()
es gibt auch eine viel präzisere Möglichkeit - geben Sie den Standardrückgabewert an:Sofern Sie
pop()
nicht den Wert eines zu entfernenden Schlüssels ermitteln, können Sie alles angeben, was nicht erforderlich istNone
. Es kann jedoch sein, dass die Verwendungdel
mitin
Check etwas schneller ist, da es sichpop()
um eine Funktion mit eigenen Komplikationen handelt, die Overhead verursachen. Normalerweise ist dies nicht der Fall, daher ist derpop()
Standardwert gut genug.Bei der Hauptfrage müssen Sie eine Kopie Ihres Wörterbuchs erstellen, um das ursprüngliche Wörterbuch zu speichern und ein neues zu erstellen, ohne dass der Schlüssel entfernt wird.
Einige andere Leute hier schlagen vor, eine vollständige (tiefe) Kopie mit zu
copy.deepcopy()
erstellen, was ein Overkill sein könnte, eine "normale" (flache) Kopie mitcopy.copy()
oderdict.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 und nicht das Objekt, auf das verwiesen wird. Das Objekt selbst kann später vom Garbage Collector automatisch entfernt werden, wenn keine anderen Referenzen im Speicher vorhanden sind. Das Erstellen einer tiefen Kopie erfordert im Vergleich zu einer flachen Kopie mehr Berechnungen. Daher 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 tiefe Kopie erstellen.
Mit flacher Kopie:
Mit tiefer Kopie:
quelle
A
dict
ist die falsche Datenstruktur.Sicher, das Kopieren des Diktats und das Herausspringen aus der Kopie funktionieren ebenso wie 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 Kopien, die gleichzeitig lebendig sind, nehmen Platz ein - linearer Raum pro Kopie.
Andere Datenstrukturen, wie z. B. Versuche mit Hash-Array-Zuordnung , sind genau für diesen Anwendungsfall konzipiert: Durch Hinzufügen oder Entfernen eines Elements wird eine Kopie in logarithmischer Zeit zurückgegeben, wobei der größte Teil des Speichers mit dem Original geteilt wird .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 identisch machen können,
dict
unterscheidet sich die "mutierende" API offensichtlich. Und vor allem sind in Python keine HAMT-Batterien enthalten. 2Die
pyrsistent
Bibliothek ist eine ziemlich solide Implementierung von HAMT-basierten Dikt-Ersetzungen (und verschiedenen anderen Typen) für Python. Es hat sogar eine raffinierte Evolver-API, um vorhandenen Mutationscode so reibungslos wie möglich auf persistenten Code zu portieren. Wenn Sie jedoch explizit Kopien zurückgeben möchten, anstatt sie zu mutieren, verwenden Sie sie einfach wie folgt:Das
d3 = d1.remove('a')
ist genau das, was die Frage ist zu fragen.Wenn Sie veränderbare Datenstrukturen wie
dict
undlist
eingebettet in haben,pmap
treten immer noch Aliasing-Probleme auf. Sie können dies nur beheben, indem Sie unveränderlich nach unten gehen undpmap
s undpvector
s einbetten .1. HAMTs sind auch in Sprachen wie Scala, Clojure, Haskell populär geworden, weil sie sehr gut mit sperrfreier Programmierung und Software-Transaktionsspeicher spielen, aber keine davon ist in Python sehr relevant.
2. Tatsächlich gibt es in der stdlib ein HAMT, das bei der Implementierung von verwendet wird
contextvars
. Das früher zurückgezogene PEP erklärt warum. Dies ist jedoch ein verstecktes Implementierungsdetail der Bibliothek, kein öffentlicher Sammlungstyp.quelle
Ergebnis:
d = {1: 2, '2': 3}
quelle
Rufen Sie einfach del d ['key'] auf.
In der Produktion ist es jedoch immer eine gute Praxis, zu überprüfen, ob in d 'Schlüssel' vorhanden ist.
quelle
try-except
Block. Zumindest wird dies eine atomare Operation sein;)d.pop('key', None)
präzise sein möchten, verwenden Sie es als Oneliner. Die eigentliche Frage war jedoch, das Wörterbuch ohne einen Schlüssel zu erhalten und nicht das Diktat zu ändern. Also Verständnis - ist hier eine gute Wahl;)Nein, es gibt keinen anderen Weg als
Das Erstellen von Kopien nur geringfügig veränderter Wörterbücher ist jedoch wahrscheinlich keine gute Idee, 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.
quelle
quelle
Dies führt zu keiner Fehlerbehandlung. Es wird davon ausgegangen, dass sich der Schlüssel im Diktat befindet. Möglicherweise möchten Sie dies zuerst überprüfen, und
raise
wenn dies nicht der Fall istquelle
del test_dict[key]
?Hier ein Top-Level-Design-Ansatz:
Ich übergebe das Wörterbuch und den gewünschten Schlüssel in meine Funktion, überprüfe, ob es sich um ein Wörterbuch handelt und ob der Schlüssel in Ordnung ist. Wenn beide vorhanden sind, wird der Wert aus dem Wörterbuch entfernt und die Reste ausgedruckt.
Ausgabe:
{'B': 55, 'A': 34}
Ich hoffe, das hilft!
quelle
Das folgende Code-Snippet wird Ihnen definitiv helfen. Ich habe in jeder Zeile Kommentare hinzugefügt, die Ihnen beim Verständnis des Codes helfen.
oder Sie können auch dict.pop () verwenden
oder der bessere Ansatz ist
quelle
Hier ist eine weitere Variante, die das Listenverständnis verwendet:
Der Ansatz basiert auf einer Antwort aus diesem Beitrag: Effiziente Methode zum Entfernen von Schlüsseln mit leeren Zeichenfolgen aus einem Diktat
quelle
if v
umif k is not 'a'
die op zu beantworten. Aber ich denke nicht, dass dies ein effizienter Weg ist. Dadurch wird das Element in O (n) und nicht in O (log n) entfernt, wie dies bei Pop oder Del der Fall ist.Mit dem folgenden Code wird eine Kopie von Diktaten erstellt
species
und Elemente gelöscht, die nicht enthalten sindtrans_HI
quelle