Deleting from a list while iterating

Rhamphoryncus rhamph at gmail.com
Sun Dec 3 11:27:09 EST 2006


Martin v. Löwis wrote:
> Rhamphoryncus schrieb:
> > setapproach = """\
> > def func(count):
> >     from random import random
> >     items = [random() for i in xrange(count)]
> >     remove = set()
> >     for index, x in enumerate(items):
> >         #...do something...
> >         if x < 0.5:
> >             remove.add(index)
> >     items = [x for index, x in enumerate(items) if index not in remove]
> > """
>
> This is different from the other approaches in that it doesn't
> modify items. If you wanted a new list, you could incrementally
> build one already in the first pass, no need to collect the
> indices first (as BlackJack explains).

I didn't feel this distinction was worth mentioning, since "oldlist[:]
= newlist" is so trivial.  The only solution that really avoids making
a copy is the reverse-iteration one.


> If you wanted in-place modification, I'd do
>
>      newitems = []
>      for x in items:
>         if not (x < 0.5):
>            newitems.append(x)
>      items[:] = newitems

I agree, that does seem simpler.


> > copyapproach = """\
> > def func(count):
> >     from random import random
> >     items = [random() for i in xrange(count)]
> >     for x in items[:]:
> >         if x < 0.5:
> >             items.remove(x)
> > """
>
> This happens to work for your example, but is incorrect
> in the general case: you meant to write
>
>               del items[i+removed]
>
> here, as .remove(x) will search the list again, looking
> for the first value to remove. If your condition for
> removal happens to leave some items equal to x in the
> list, it would remove the wrong item. Because the numbering
> changes while the iteration is in progress, you have
> to count the number of removed items also.

I agree that the example I gave here sucks.  However, I copied it from
another posting as a recommended method to get removal to work *right*
(without noticing how slow it is).

There seems to have been many distinct approaches to this problem over
the years.  Hopefully we can converge on a single ideal solution (or a
few situational ones) as TOOWTDI.

-- 
Adam Olsen, aka Rhamphoryncus




More information about the Python-list mailing list