Comment éviter de "RuntimeError: dictionnaire changé de taille au cours d'une itération d'erreur"?

J'ai vérifié toutes les autres questions avec la même erreur encore trouvé aucune solution utile =/

J'ai un dictionnaire de listes:

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

Dans lequel certaines valeurs sont vides. À la fin de la création de ces listes, je veux supprimer ces listes vides avant de retourner mon dictionnaire. Courant, j'essaie de le faire comme suit:

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

Cependant, cela me donne l'erreur d'exécution. Je suis conscient que vous ne pouvez pas ajouter/supprimer des éléments dans un dictionnaire lors de l'itération à travers elle...ce serait un moyen de contourner cela, alors?

127
demandé sur gsamaras 2012-08-14 00:30:07

5 réponses

En Python 2.x appelant keys fait une copie de la clé que vous pouvez parcourir en modifiant le dict:

for i in d.keys():

Notez que cela ne fonctionne pas en Python 3.x parce que keys renvoie un itérateur au lieu d'une liste.

Une Autre façon est d'utiliser list pour forcer une copie des clés pour être fait. Celui-ci fonctionne également en Python 3.x:

for i in list(d):
254
répondu Mark Byers 2016-05-11 19:16:43

Il suffit D'utiliser la compréhension du dictionnaire pour copier les éléments pertinents dans un nouveau dict

>>> 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]}
22
répondu Maria Zverina 2012-08-13 20:38:00

Il vous suffit d'utiliser "copy":

De cette façon, vous parcourez les champs du dictionnaire d'origine et, à la volée, vous pouvez modifier le dict souhaité (d dict). C'est du travail sur chaque version de python, donc c'est plus clair.

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]}
17
répondu Alon Elharar 2016-06-13 14:37:46

J'essaierais d'éviter d'insérer des listes vides en premier lieu, mais, utiliserait généralement:

d = {k: v for k,v in d.iteritems() if v} # re-bind to non-empty

Si avant 2.7:

d = dict( (k, v) for k,v in d.iteritems() if v )

Ou tout simplement:

empty_key_vals = list(k for k in k,v in d.iteritems() if v)
for k in empty_key_vals:
    del[k]
11
répondu Jon Clements 2012-08-13 20:42:10

Pour Python 3:

{k:v for k,v in d.items() if v}
5
répondu ucyo 2018-05-16 07:47:20