Python Forum

Full Version: .remove() from a list - request for explanation
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Hi guys,

I am learning python and I came across a weird thing which is hard for me to find the cause of it.
Here is my code:
l = [1, 2, 3, 2, 2, 2, 1]
for el in l:
  print("element: ", el)
  if el == 2:
    l.remove(el)
    print("list after removing el == 2: ", l)
  print("list for the next iteration: ", l)
Seriously, I don't know why the last number 2 is not taken into consideration to the next iteration of for-loop. Could anyone know the reason and may brighten up my mind, please?

[EDIT]
I added some comments to be printed and my idea is that after each iteration in which an element was removed, the length of the list is shorten, but the number of iteration is increasing and finally we have the length of a list equals 4 and the number of iteration is 4, so we cannot make any further iteration. Am I right? How could we fix that problem, does anybody have an idea?
l = [1, 2, 3, 2, 2, 2, 1]
for el in l:
  print('len list at the beginning of a new iteration: ', len(l))
  print("element: ", el)
  if el == 2:
    l.remove(el)
    print("list after removing el == 2: ", l)
    print('len list strict after removing el == 2: ', len(l))
  print("list for the next iteration: ", l)
  print('len list at the end of an iteration: ', len(l))
It's a know bad pattern to remove element in a list/collection while iterate over it.
Will mess up list index and will get your result.
There is a easy fix if add l[:]: then iterate over a copy,
but it's slow as remove() has to go over the whole list for every iteration O(n^2).

So a couple of ways.
l = [1, 2, 3, 2, 2, 2, 1]
result = []
for el in l:
    if el != 2:
        result.append(el)
print(result) 
Output:
[1, 3, 1]
The same with list comprehension.
>>> l = [1, 2, 3, 2, 2, 2, 1]
>>> [el for el in l if el != 2]
[1, 3, 1]
Don't modify an iterator while you're iterating over it. Some options are to loop over a copy of the list or to just copy the data you do want rather than delete the data you don't.

l = [1, 2, 3, 2, 2, 2, 1]
    for el in l[:]:  # loops over a copy of l.  Modifying l doesn't change the loop iterator.
    ...
l = [1, 2, 3, 2, 2, 2, 1]
l = [e for e in if l != 2]  # list comprehension copies the data we want directly
@snippsat, @bowlofred - thank you for explanation