It's important to understand what is happening because modification during iteration is a common problem if it's not done right
Here is a simple list
0, 1, 2, 3, 4, 5
When idx = 1
, you drop element 1
:
0, 2, 3, 4, 5
^
Then you increment idx
two more times before dropping another element:
0, 2, 3, 4, 5
^
So now you have
0, 2, 3, 5
Luckily (or unluckily), a list iterator allows you to modify the underlying data without breaking.
There are a couple of ways to fix this. The first one is to iterate backwards. Also, don't iterate over a collection when you modify it, keep the index external. You can still use a for
loop though:
for idx in range(len(elements) - 1, -1, -1):
if idx % 2:
del elements[idx]
Don't forget to use del
to drop elements by index instead of value.
If you're absolutely sure that the input has an even size, you can remove the conditional easily:
for idx in range(len(elements) - 1, -1, -2):
del elements[idx]
For an arbitrary number of elements, it's only slightly more complicated to avoid the last potentially even element:
for idx in range(len(elements) // 2 * 2 - 1, -1, -2):
del elements[idx]
In python, there are short-hand indices you can use to drop the elements directly. To do it in-place:
del elements[1::2]
Or the more commonly suggested option of making a copy:
elements = elements[::2]