Re: [Tutor] iterating over a changing list
On 11/10/12 08:49, eryksun wrote: Also, generally avoid mutating a list while iterating over it. listiterator is just incrementing an index, so modifying the size of the list can produce nonsense (e.g. if you remove the current item, the next item will be skipped). Instead, create an empty list and append() to it. If you absolutely have to modify the list you are iterating over, iterate over it backwards: # this doesn't work correctly for i in range(len(mylist)): x = mylist[i] if x < 0: del mylist[i] # this does for i in range(len(mylist)-1, -1, -1): x = mylist[i] if x < 0: del mylist[i] But really, don't do that either. Iterate over a copy, or make a new list with the items you want. It's faster and easier. -- Steven ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] iterating over a changing list
On Wed, Oct 10, 2012 at 3:52 PM, Ed Owens wrote: > > import string Why are you importing "string"? Most string functions one would need are methods of str/unicode. Sometimes "string" is still required, however. > def add_element(items, point): > items = items[:point+1][:] + [['new']] + items[point+1:] > return items items[:point+1][:] creates a copy of part of the list with the slice [:point+1], and then it copies the copy with the slice [:]. Redundant operations aside, this is returning a new list object. That's not going to work since the loop iterator is bound to the original list. You can't rebind a listiterator in the middle of a for loop. Also, generally avoid mutating a list while iterating over it. listiterator is just incrementing an index, so modifying the size of the list can produce nonsense (e.g. if you remove the current item, the next item will be skipped). Instead, create an empty list and append() to it. ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] iterating over a changing list
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 ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] iterating over a changing list
On 10/10/2012 20:52, 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 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) 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? Thanks in advance for any help. Ed ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor Usually handled by iterating over a copy of the list. for itm in itmlst[:]: -- Cheers. Mark Lawrence. ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor