>>> mylist = ['bunnies', 'apples', 'animals', 'fruit', 'amsterdam']
>>> for x in mylist:
	print '--------------'
	print x
	if x[0] == 'a':
		print "Removing ",x
		mylist.remove(x)

		
--------------
bunnies
--------------
apples
Removing  apples
--------------
fruit
--------------
amsterdam
Removing  amsterdam
>>> print mylist
['bunnies', 'animals', 'fruit']

The output should be bunnies and fruit, animals should have been removed because it starts with an a...

I'm very confused why this isn't working, but I'm assuming that it has something to do with looping through a list while removing parts of it... Does anybody have a clearer answer for this?

Dani AI

Generated

This is happening because the loop's internal index keeps moving forward while the list shrinks when you remove an element. The next element slides into the removed slot but the loop advances to the next index, so that newly shifted element is skipped. That is why saw the second run remove the previously skipped item — the second pass sees the element that was skipped on the first pass.

A quick trace (conceptual):

  • start: ['bunnies', 'apples', 'animals', 'fruit', 'amsterdam']
  • loop yields index 0 -> 'bunnies' (kept)
  • loop yields index 1 -> 'apples' (removed). List now has 'animals' at index 1.
  • loop advances to index 2 -> sees 'fruit'. 'animals' at index 1 was never examined.

As and noted, iterating over a copy or constructing a new list avoids the problem. Another in-place option that isn't shown above is to iterate the indices in reverse and delete by index; because removals only affect later (higher) indices, nothing gets skipped. Example:

for i in range(len(mylist) - 1, -1, -1):
    if mylist[i].startswith('a'):
        del mylist[i]

Caveats:

  • Repeated deletions from the middle of a Python list are expensive (O(n) per deletion), so for large lists prefer making a new filtered list (linear time) instead of many in-place deletes.
  • The behavior described is due to how the for-loop advances; the Python docs explain the for-statement semantics if a precise, language-level description is wanted: the for statement.

Recommended Answers

All 4 Replies

Here i make a copy of the list,then iterating over it.
It is not a good ideé to delete/add somthing from a list you are iterating over.
The solution is to make a copy or new list.

mylist = ['bunnies', 'apples', 'animals', 'fruit', 'amsterdam']

for item in mylist[:]:
	if item[0] == 'a':
            mylist.remove(item)
print mylist

'''
output--->
['bunnies', 'fruit']
'''

This maybe easyer to read.

lst = ['bunnies', 'apples', 'animals', 'fruit', 'amsterdam']
    
new_lst = []
for item in lst:
        if item[0] != 'a':
            new_lst.append(item)
print new_lst

'''
output--->
['bunnies', 'fruit']
'''

Or maybe a more elegant solution with a function

def list_remove(item):   
        if item[0] == 'a':
            return False
        return True
    
lst = ['bunnies', 'apples', 'animals', 'fruit', 'amsterdam']
lst1 = [item for item in lst if list_remove(item)]
print lst1

'''
output--->
['bunnies', 'fruit']
'''
Member Avatar for Member #531174

Hey, I too was totally confused by your problem, it happened to me too! But, I tried this:

>>> mylist = ['bunnies', 'apples', 'animals', 'fruit', 'amsterdam']
>>> for x in mylist:
	print '--------------'
	print x
	if x[0] == 'a':
		print "Removing ",x
		mylist.remove(x)

		
--------------
bunnies
--------------
apples
Removing  apples
--------------
fruit
--------------
amsterdam
Removing  amsterdam
>>> print mylist
['bunnies', 'animals', 'fruit']
>>> for x in mylist:
	print '--------------'
	print x
	if x[0] == 'a':
		print "Removing ",x
		mylist.remove(x)

		
--------------
bunnies
--------------
animals
Removing  animals
>>>

All I did was run the for loop twice, and it worked, but I still have no idea why this is happening! :?:

Like snippsat so wisely said,
"do not change a list that your are iterating over"
this will upset the indexing of the list during the iteration process.

snippsat also recommended to iterate over a copy of mylist:

mylist = ['bunnies', 'apples', 'animals', 'fruit', 'amsterdam']
mylist_copy = list(mylist)  # or mylist[:]
for x in mylist_copy:
    print '--------------'
    print x
    if x[0] == 'a':
        print "Removing ",x
        mylist.remove(x)

print mylist

"""
my output -->
--------------
bunnies
--------------
apples
Removing  apples
--------------
animals
Removing  animals
--------------
fruit
--------------
amsterdam
Removing  amsterdam
['bunnies', 'fruit']
"""

Very interesting little caveat there. But, thanks all for the helpful code snippets. Solved.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.