¿Cómo puedo evitar el error "RuntimeError: el diccionario cambió de tamaño durante la iteración"?
Supongamos que tengo un diccionario de listas:
d = {'a': [1], 'b': [1, 2], 'c': [], 'd':[]}
Ahora quiero eliminar pares clave-valor donde los valores son listas vacías. Probé este código:
for i in d:
if not d[i]:
d.pop(i)
pero esto da un error:
RuntimeError: dictionary changed size during iteration
Entiendo que no se pueden agregar ni eliminar entradas de un diccionario mientras se recorre en iteración. ¿Cómo puedo solucionar esta limitación para resolver el problema?
Consulte Modificar un dictado de Python mientras se itera sobre él para conocer las citas que pueden causar problemas y por qué.
En Python 3.x y 2.x puedes usar use list
para forzar la realización de una copia de las claves:
for i in list(d):
En Python 2.x, las llamadas .keys
hacían una copia de las claves que podía iterar mientras modificaba dict
:
for i in d.keys():
pero en Python 3.x, .keys
devuelve un objeto de vista , por lo que no solucionará el error.
Sólo necesitas usar copy
:
De esta manera, itera sobre los campos del diccionario original y sobre la marcha puede cambiar el dictado deseado d
. Funciona en cada versión de Python, por lo que es más claro.
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]}
(Por cierto, generalmente para iterar sobre la copia de su estructura de datos, en lugar de usar .copy
para diccionarios o dividir [:]
para listas, puede usar import copy
-> copy.copy
(para una copia superficial que es equivalente a copy
la que admiten diccionarios o la división [:]
que es compatible con listas) o copy.deepcopy
en su estructura de datos.)
Simplemente use la comprensión del diccionario para copiar los elementos relevantes en un nuevo dictado:
>>> 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]}
Para esto en 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]}