507 Stimmen

Wie kann ich den Fehler "RuntimeError: dictionary changed size during iteration" vermeiden?

Ich habe ein Wörterbuch mit Listen, in dem einige der Werte leer sind:

d = {'a': [1], 'b': [1, 2], 'c': [], 'd':[]}

Am Ende der Erstellung dieser Listen möchte ich diese leeren Listen entfernen, bevor ich mein Wörterbuch zurückgeben kann. Ich habe versucht, es so zu machen:

for i in d:
    if not d[i]:
        d.pop(i)

aber ich habe eine RuntimeError . Ich bin mir bewusst, dass man keine Elemente in einem Wörterbuch hinzufügen/entfernen kann, während man es durchläuft ... wie könnte man das dann umgehen?


Voir <a href="https://stackoverflow.com/questions/6777485/">Ändern eines Python-Diktats bei der Iteration über das Diktat </a>für Zitate, die zeigen, dass dies zu Problemen führen kann, und warum.

788voto

Mark Byers Punkte 761508

In Python 3.x und 2.x können Sie use verwenden list um die Anfertigung einer Kopie der Schlüssel zu erzwingen:

for i in list(d):

In Python 2.x ist der Aufruf von keys eine Kopie der Schlüssel erstellt, die Sie beim Ändern der dict :

for i in d.keys():

Aber beachten Sie, dass in Python 3.x diese zweite Methode nicht mit Ihrem Fehler helfen, weil keys gibt ein a Objekt anzeigen anstatt die Schlüssel in eine Liste zu kopieren.

132voto

Alon Elharar Punkte 1189

Sie müssen nur Folgendes verwenden copy :

Auf diese Weise können Sie über die ursprünglichen Wörterbuchfelder iterieren und das gewünschte Diktat im Handumdrehen ändern d . Es funktioniert mit jeder Python-Version, so dass es übersichtlicher ist.

In [1]: d = {'a': [1], 'b': [1, 2], 'c': [], 'd':[]}

In [2]: for i in d.copy():
   ...:     if not d[i]:
   ...:         d.pop(i)
   ...:         

In [3]: d
Out[3]: {'a': [1], 'b': [1, 2]}

(BTW - Generell über die Kopie Ihrer Datenstruktur zu iterieren, anstatt mit .copy für Wörterbücher oder Slicing [:] für Listen verwenden, können Sie import copy -> copy.copy (für eine oberflächliche Kopie, die gleichbedeutend ist mit copy die durch Wörterbücher oder Slicing unterstützt wird [:] die von Listen unterstützt wird) oder copy.deepcopy auf Ihre Datenstruktur).

70voto

Maria Zverina Punkte 10373

Verwenden Sie einfach Wörterbuchverständnis um die entsprechenden Elemente in ein neues Diktat zu kopieren:

>>> d
{'a': [1], 'c': [], 'b': [1, 2], 'd': []}
>>> d = {k: v for k, v in d.items() if v}
>>> d
{'a': [1], 'b': [1, 2]}

Für diese in Python 2:

>>> d
{'a': [1], 'c': [], 'b': [1, 2], 'd': []}
>>> d = {k: v for k, v in d.iteritems() if v}
>>> d
{'a': [1], 'b': [1, 2]}

40voto

singrium Punkte 2594

Das hat bei mir funktioniert:

d = {1: 'a', 2: '', 3: 'b', 4: '', 5: '', 6: 'c'}
for key, value in list(d.items()):
    if value == '':
        del d[key]
print(d)
# {1: 'a', 3: 'b', 6: 'c'}

Die Umwandlung der Wörterbucheinträge in eine Liste erzeugt eine Liste der Einträge, so dass Sie darüber iterieren können und die RuntimeError .

17voto

K.A Punkte 635

Um den Fehler "Wörterbuchgröße während der Iteration geändert" zu vermeiden.

Zum Beispiel: "wenn Sie versuchen, eine Taste zu löschen",

Verwenden Sie einfach 'list' mit '.items()'. Hier ist ein einfaches Beispiel:

my_dict = {
    'k1':1,
    'k2':2,
    'k3':3,
    'k4':4

    }

print(my_dict)

for key, val in list(my_dict.items()):
    if val == 2 or val == 4:
        my_dict.pop(key)

print(my_dict)

Ausgabe:

{'k1': 1, 'k2': 2, 'k3': 3, 'k4': 4}

{'k1': 1, 'k3': 3}

Dies ist nur ein Beispiel. Ändern Sie es je nach Ihrem Fall/Anforderungen.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X