modifying a list while iterating through

Steven D'Aprano steve at REMOVE.THIS.cybersource.com.au
Mon Feb 26 17:21:51 EST 2007


On Mon, 26 Feb 2007 13:45:36 -0800, dustin.getz wrote:

> My original question still stands, though, in situations where a
> simple string replacement might not be sufficient.  Is there a way to
> insert into a list whilst iterating through it?

Inserting/deleting from a list while you're walking through it is *always*
tricky, by its very nature.

Deletions are easy to deal with: iterate over the list backwards. When
you delete the current item, the only items that are re-numbered are items
you've already looked at.

Similarly, if you iterate backwards over the list and make sure you only
insert after the current item, never before, you can avoid re-numbering
items you haven't looked at yet.

Another solution is to iterate over the list, creating a new list as you
go:

new = []
for item in some_list:
    if condition:
        # delete the item
        pass
    elif other_condition:
        # insert something
        new.extend(['something', item])
    else:
        new.append(item)





> for example, consider a list of binary values.
> 
> for index in range(len(iterable)):
>   item=iterable[index]

The Pythonic way to write that is 

for index,item in enumerate(iterable):
    pass


>   if item==1:
>      iterable.insert(index,0)

"Iterables" are sequences and iterators -- anything you can iterate over.
In general, only sequences can be inserted into (and not even all
sequences).


> obv this wouldn't work because now all future indexes will be off by the
> number of previously inserted items.
> 
> using a while loop to fix this ugly and counterintuitive.

Well, if you insist on doing a tricky job, you're always going to have
tricky code. Here's one solution:

# inserting into a mutable sequence
sequence.reverse()
for index in range(len(sequence)-1, -1, -1):
    item = sequence[index]
    if item == 1:
        sequence.insert(index+1, 0)
sequence.reverse()


Here's a solution that should work for any iterable, provided you have
sufficient memory:

# inserting into a copy of iterable
copy = []
for item in iterable:
    if item == 1:
        copy.append(0)
    copy.append(item)


Hope this helps.


-- 
Steven.




More information about the Python-list mailing list