YJZ
YJZ

Reputation: 4214

remove items when looping/iterating a list

I see some discussion about how to handle the task of "delete items when looping a list", e.g., this post.

An answer in this link says:

You are not permitted to remove elements from the list while iterating over it using a for loop.

It seems I can do it without problem:

words = ['DROP', 'TABLE', 'table_name']

for ii, word in enumerate(words):

    print(ii)
    print(word)

    if words[ii] == 'DROP' and words[ii + 1] == 'TABLE':    
        words[ii] = 'DROP TABLE'
        del words[ii + 1]

print(words)

yields:

0
DROP
1
table_name
['DROP TABLE', 'table_name']

Has python changed the restriction and we can remove items when looping now? I'm using python 3.7.

Upvotes: 0

Views: 179

Answers (3)

pocza
pocza

Reputation: 710

There is (and also was) absolutely nothing stopping you from modifying the list you are iterating through (dictionaries can't be modified in python3 though - results in an error), but the results can be... surprising. Even your question is based on such surprising result - you don't have an error, because you look ahead and you "merge" two results into one. If you would ONLY remove every DROPyou would end up missing some entries:

words = ['DROP', 'one_drop_will_be_missed', 'DROP', 'DROP' ]

for ii, word in enumerate(words):
    print(ii)
    print(word)
    if words[ii] == 'DROP':
        del words[ii]

print(words)

Results in a:

0
DROP
1
DROP
['one_drop_will_be_missed', 'DROP']

What would happen if somehow DROP would be the last word in your list?

Upvotes: 1

tdelaney
tdelaney

Reputation: 77407

That statement is technically wrong but reasonable for most use cases. You most certainly can remove items from a list while enumerating but be aware that you will end up skipping elements if you do so. You want that to happen in your case - the enumeration skips the 'TABLE' entry by doing a lookahead into the not-yet-enumerated list (words[ii + 1] == 'TABLE') and trimming. But that is an uncommon use case.

Upvotes: 1

MooingRawr
MooingRawr

Reputation: 5001

From the comment of the answer you provided:

"You are not permitted" - sure you are. Python doesn't complain at you, it just gives a slightly (read: completely) different result to what people might expect. – lvc May 19 '12 at 14:00

You could always remove items from for loops, but it will skip the iteration when looping through. Take this example to see what happens (both ran through Python 2.7 and Python 3.5 giving the same result, of course Python 2 had print i):

i=[1,2,3,4,5,6]

for x in i:
    i.remove(x)

print(i) #[2, 4, 6] 

Notice how it skips index 2,4,6? it's because when you removed value 1 in index 0, value 2 becomes the new index 0, and the for loop will take value 3 as the next index.

There's nothing new about it. Generally it's a bad idea to remove items directly from a list while iterating through it.


The reason why your codes seems fine is cause you purposely dropped the index 1, which is what you desired.

Upvotes: 3

Related Questions