[Tutor] iterating over a changing list

Dave Angel d at davea.name
Wed Oct 10 23:09:13 CEST 2012


On 10/10/2012 03:52 PM, Ed Owens wrote:
> I'm trying to iterate over a list of elements, and make changes to the list
> in front of the element I'm currently working with.  I can update the list,
> but the  'for'  doesn't see the new element.  Here's the code:
>
> import string
>
> def add_element(items, point):
>     items = items[:point+1][:] + [['new']] + items[point+1:]
>     return items
This function doesn't change its input object at all, it's just creates
and returns a new one.
> def main():
>     pass
>
> itmlst = [['a'],['b']]
> itmcntr = 0
>
> for itm in itmlst:
>     cmd = ''
>     while True:
>         cmd = raw_input('break, add, print:')
>         if cmd == 'break':
>             break
>         elif cmd == 'add':
>             itmlst = add_element(itmlst,itmcntr)

Now you've created a brand new list, and bound it to the itemlst
variable, but you're still iterating over the original list.

>         elif cmd == 'print':
>             print 'current item:', itm
>         else:
>             print 'invalid'
>     itmcntr += 1
>     print 'finished with', itm, 'in', itmlst
> print len(itmlst), 'total items in list'
>
> If I provide the inputs: [print add print break print break] at the prompt,
> I get this output
>
> current item: ['a']
> current item: ['a']
> finished with ['a'] in [['a'], ['new'], ['b']]
> current item: ['b']
> finished with ['b'] in [['a'], ['new'], ['b']]
> 3 total items in list
>
> The new element got added, but it wasn't used in the iteration over the list
> of items. Other than setting up a counter and calling len() each loop, is
> there some way to have the changing list recognized within the for loop?
>
>

Usually, people have the reverse problem, one of seeming to stutter on
one of the items, or skipping one.  And the cure for either of those is
(as Mark tried to point out) to make a new list object to iterate over.

if you're sure you want to insert items in the original list that you're
looping on, then you need to change two places.  One is the
add_element() function needs to either use the insert() or an equivalent
set of slices.  use the insert() method, since it's easier.  And don't
bother returning the list, since you're not creating a new one. 
Convention is to either return a new object, or modify an object in
place, but not both.

The other place to change is the place where you call that function.  It
should NOT bind the variable to the return value, since it doesn't want
a new list object.

I haven't studied the rest of your code, as it didn't make much sense to
me.  But it's probably a simplified version of whatever you are trying
to do, so that should be fine.



-- 

DaveA



More information about the Tutor mailing list