Deleting from a list while iterating

"Martin v. Löwis" martin at v.loewis.de
Sun Dec 3 11:08:00 EST 2006


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).

If you wanted in-place modification, I'd do

     newitems = []
     for x in items:
        if not (x < 0.5):
           newitems.append(x)
     items[:] = newitems

> 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.

Regards,
Martin



More information about the Python-list mailing list