¿Cómo eliminar elementos de la lista en un bucle for en Python? [duplicar]

Resuelto alwbtc asked hace 12 años • 6 respuestas

tengo una lista

a = ["a", "b", "c", "d", "e"]

Quiero eliminar elementos de esta lista en un bucle for como el siguiente:

for item in a:
    print(item)
    a.remove(item)

Pero no funciona. ¿Qué puedo hacer?

alwbtc avatar May 19 '12 20:05 alwbtc
Aceptado

No está permitido eliminar elementos de la lista mientras se itera sobre ella mediante un forbucle.

La mejor manera de reescribir el código depende de lo que estés intentando hacer.

Por ejemplo, su código es equivalente a:

for item in a:
    print(item)
a[:] = []

Alternativamente, puedes usar un whilebucle:

while a:
    print(a.pop())

Estoy intentando eliminar elementos si coinciden con una condición. Luego paso al siguiente elemento.

Puedes copiar cada elemento que no coincida con la condición en una segunda lista:

result = []
for item in a:
    if condition is False:
        result.append(item)
a = result

Alternativamente, puede usar filtero una lista por comprensión y asignar el resultado nuevamente a a:

a = filter(lambda item:... , a)

o

a = [item for item in a if ...]

donde ...representa la condición que necesita verificar.

NPE avatar May 19 '2012 13:05 NPE

Iterar a través de una copia de la lista:

>>> a = ["a", "b", "c", "d", "e"]
>>> for item in a[:]:
    print(item)
    if item == "b":
        a.remove(item)

a
b
c
d
e
>>> print(a)
['a', 'c', 'd', 'e']
Alex L avatar May 19 '2012 13:05 Alex L

Como han dicho otras respuestas, la mejor manera de hacerlo implica crear una nueva lista, ya sea iterar sobre una copia o construir una lista con solo los elementos que desea y asignarla nuevamente a la misma variable. La diferencia entre estas depende de su caso de uso, ya que afectan a otras variables de la lista original de manera diferente (o, más bien, la primera las afecta, la segunda no).

Si una copia no es una opción por algún motivo, tiene otra opción que depende de comprender por qué se interrumpe la modificación de una lista que está iterando. La iteración de listas funciona realizando un seguimiento de un índice, incrementándolo cada vez que recorre el ciclo hasta que sale del final de la lista. Entonces, si elimina en (o antes) el índice actual, todo desde ese punto hasta el final se desplaza un lugar hacia la izquierda. Pero el iterador no sabe acerca de esto y efectivamente omite el siguiente elemento ya que ahora está en el índice actual en lugar del siguiente. Sin embargo, eliminar cosas que están después del índice actual no afecta las cosas.

Esto implica que si itera la lista de atrás hacia adelante, si elimina un elemento en el índice actual, todo lo que está a la derecha se desplaza hacia la izquierda, pero eso no importa, ya que ya se ha ocupado de todos los elementos a la derecha de la posición actual y te estás moviendo hacia la izquierda; el siguiente elemento a la izquierda no se ve afectado por el cambio, por lo que el iterador te proporciona el elemento que esperas.

TL;DR:

>>> a = list(range(5))
>>> for b in reversed(a):
    if b == 3:
        a.remove(b)
>>> a
[0, 1, 2, 4]

Sin embargo, hacer una copia suele ser mejor porque hace que el código sea fácil de leer. Sólo menciono esta posibilidad en aras de la exhaustividad.

lvc avatar May 19 '2012 13:05 lvc