Deleting a List Item While Iterating
Let’s trim a long list and list the list.
list_1 = [1, 2, 3, 4]list_2 = [1, 2, 3, 4]list_3 = [1, 2, 3, 4]list_4 = [1, 2, 3, 4]for idx, item in enumerate(list_1):del itemfor idx, item in enumerate(list_2):list_2.remove(item)for idx, item in enumerate(list_3[:]):list_3.remove(item)for idx, item in enumerate(list_4):list_4.pop(idx)print(list_1)print(list_2)print(list_3)print(list_4)
Can you guess why the output is [2, 4]
?
Explanation
- It’s never a good idea to change the object that you’re iterating over. The correct way to do so is to iterate over a copy of the object instead, and
list_3[:]
does just that.
some_list = [1, 2, 3, 4]print(id(some_list))print(id(some_list[:])) # Notice that python creates new object for sliced list.
The difference between del
, remove
, and pop
:
del var_name
just removes the binding of thevar_name
from the local or global namespace (that’s why thelist_1
is unaffected).remove
removes the first matching value, not a specific index, and raisesValueError
if the value is not found.pop
removes the element at a specific index and returns it, and raisesIndexError
if an invalid index is specified.
Why is the output [2, 4]
?
- The list iteration is done index by index, and when we remove
1
fromlist_2
orlist_4
, the contents of the lists are now[2, 3, 4]
. The remaining elements are shifted down, i.e.,2
is at index 0, and3
is at index 1. Since the next iteration is going to look at index 1 (which is the3
), the2
gets skipped entirely. A similar thing will happen with every alternate element in the list sequence.