[pyar] Remover elementos de una lista mientras se la recorre

Claudio Freire klaussfreire en gmail.com
Lun Dic 27 13:14:29 ART 2010


2010/12/27 Ricardo Armas <rarmas en gmail.com>

> 2010/12/27 Juanjo Conti <jjconti en gmail.com>:
> > Lista, les comento un comportamiento que me llamó la atención:
> >
> >>>> l = range(3)
> >>>> for x in l:
> > ...     l.remove(x)
> > ...
> >>>> l
> > [1]
> >
> > Por qué queda un elemento en la lista?
> Ya sé, es así, en la primera se elimina el 0 así que el primer
> elemento pasa a ser el 1, el for en el segundo ciclo pasa al segundo
> elemento que es el 2, por eso queda el 1 en la lista.
>

Exacto, el iterador de listas es un contador.

for x in l:
   ...

equivale a

ix = 0
while ix < len(l):
   x = l[ix]
   ix += 1
   ...

Luego, si seguís la ejecución de este último código (que es equivalente),
ves por qué queda el 1.

Sabiendo esto, tenés dos opciones:

1) crear una copia de la lista para iterarla:

for x in list(l):
    l.remove(x)

2) iterar en reverso

for x in reverse(l):
    l.remove(x)

Ojo que 2 funciona sólo porque remove() **EN ESTE CASO** no modifica la
parte futura del iterador (o sea, los índices que falta iterar), sólo
modifica lo que el iterador ya recorrió, y no cambia los índices de lo que
falta recorrer.

Pero otro caso podría funcionar mal.

Por ejemplo:

>>> l = [1,2,3,1,2,3]
>>> for x in reversed(l):
...    print x
...    l.remove(x)
...    print l
...
3
[1, 2, 1, 2, 3]
3
[1, 2, 1, 2]
2
[1, 1, 2]
2
[1, 1]
1
[1]
1
[]


La lista termina vacía, pero se ve claramente que el procedimiento no fue
como uno esperaba. Me cuesta encontrar un ejemplo donde la lista no quede
vacía, pero seguro hay alguno.
------------ próxima parte ------------
Se ha borrado un adjunto en formato HTML...
URL: <http://listas.python.org.ar/pipermail/pyar/attachments/20101227/92ca0a75/attachment.html>


More information about the pyar mailing list