Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Modifying list while iterating [duplicate]

l  = range(100)                          for i in l:                              print i,                              print l.pop(0),                       print l.pop(0) 

The above python code gives the output quite different from expected. I want to loop over items so that I can skip an item while looping.

Please explain.

like image 835
Xolve Avatar asked Oct 28 '09 14:10

Xolve


People also ask

Can I modify list while iterating?

The general rule of thumb is that you don't modify a collection/array/list while iterating over it. Use a secondary list to store the items you want to act upon and execute that logic in a loop after your initial loop.

Can you modify a collection element value while iterating using for each loop?

Use Iterator#remove . This is the only safe way to modify a collection during iteration. For more information, see The Collection Interface tutorial. If you also need the ability to add elements while iterating, use a ListIterator .

Can you modify for loops?

You can modify the loop variable in a for loop, the problem is that for loops in Python are not like "old-style" for loops in e.g. Java, but more like "new-style" for-each loops.


2 Answers

Never alter the container you're looping on, because iterators on that container are not going to be informed of your alterations and, as you've noticed, that's quite likely to produce a very different loop and/or an incorrect one. In normal cases, looping on a copy of the container helps, but in your case it's clear that you don't want that, as the container will be empty after 50 legs of the loop and if you then try popping again you'll get an exception.

What's anything BUT clear is, what behavior are you trying to achieve, if any?! Maybe you can express your desires with a while...?

i = 0 while i < len(some_list):     print i,                              print some_list.pop(0),                       print some_list.pop(0) 
like image 187
Alex Martelli Avatar answered Sep 17 '22 17:09

Alex Martelli


I've been bitten before by (someone else's) "clever" code that tries to modify a list while iterating over it. I resolved that I would never do it under any circumstance.

You can use the slice operator mylist[::3] to skip across to every third item in your list.

mylist = [i for i in range(100)] for i in mylist[::3]:     print(i) 

Other points about my example relate to new syntax in python 3.0.

  • I use a list comprehension to define mylist because it works in Python 3.0 (see below)
  • print is a function in python 3.0

Python 3.0 range() now behaves like xrange() used to behave, except it works with values of arbitrary size. The latter no longer exists.

like image 31
Ewan Todd Avatar answered Sep 20 '22 17:09

Ewan Todd