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