iterate over list while changing it

Simon Forman sajmikins at gmail.com
Fri Sep 25 00:08:05 CEST 2009


On Thu, Sep 24, 2009 at 4:32 PM, Torsten Mohr <tmohr at s.netic.de> wrote:
> Hello,
>
> a = [1, 2, 3, 4, 5, 6]
>
> for i, x in enumerate(a):
>    if x == 3:
>        a.pop(i)
>        continue
>
>    if x == 4:
>        a.push(88)
>
>    print "i", i, "x", x
>
> I'd like to iterate over a list and change that list while iterating.

This is generally a bad idea, but you can do it if you're careful.

Let's check that enumerate() works when you append to the underlying list:

In [1]: n = range(3)

In [2]: for i, x in enumerate(n):
   ...:     print i, '=>', x
   ...:     if i < 3:
   ...:         n.append(23)
   ...:
   ...:
0 => 0
1 => 1
2 => 2
3 => 23
4 => 23
5 => 23

So far so good.  But notice if you delete an item from the list while
iterating over the "enumerate object" the index returned will still be
incremented on the next iteration and you'll skip the item after the
one you just deleted:

In [1]: n = range(3)

In [2]: for i, x in enumerate(n):
   ...:     print i, '=>', x, '\t', n
   ...:     if i == 1:
   ...:         del n[i]
   ...:
   ...:
0 => 0 	[0, 1, 2]
1 => 1 	[0, 1, 2]

In [3]: n
Out[3]: [0, 2]

In [4]: n = range(6)

In [5]: for i, x in enumerate(n):
   ...:     print i, '=>', x, '\t', n
   ...:     if i == 3:
   ...:         del n[i]
   ...:
   ...:
0 => 0 	[0, 1, 2, 3, 4, 5]
1 => 1 	[0, 1, 2, 3, 4, 5]
2 => 2 	[0, 1, 2, 3, 4, 5]
3 => 3 	[0, 1, 2, 3, 4, 5]
4 => 5 	[0, 1, 2, 4, 5]



> I'd still like to work on all items in that list, which is not happening
> in the example above.
> The conditions in the example are not real but much more complex
> in reality.
>
> Can anybody tell me how to do this?

You could manage the index yourself, like so:

def f(n):
    i = 0
    while True:
        try:
            x = n[i]
        except IndexError:
            break

        print i, '=>', x

        if x == 3:
            del n[i]
            continue

        if x == 4:
            n.append(23)

        # Increment the index
        # only if you didn't
        # delete anything during
        # this iteration.
        i += 1


N = range(6)
f(N)
print N


This prints:

0 => 0
1 => 1
2 => 2
3 => 3
3 => 4
4 => 5
5 => 23
[0, 1, 2, 4, 5, 23]


HTH,
~Simon

>
> Thanks for any hints,
> Torsten.
>
>
> --
> http://mail.python.org/mailman/listinfo/python-list
>



More information about the Python-list mailing list