Strange result when removing item from a list while iterating over it in Python

for-loop, list, loops, python, range

Solution

You're modifying the list while you iterate over it. That means that the first time through the loop, `i == 1`, so `1` is removed from the list. Then the `for` loop goes to the second item in the list, which is not `2`, but `3`! Then that's removed from the list, and then the `for` loop goes on to the third item in the list, which is now 5. And so on. Perhaps it's easier to visualize like so, with a ^ pointing to the value of `i`:

[1, 2, 3, 4, 5, 6...]
 ^

That's the state of the list initially; then `1` is removed and the loop goes to the second item in the list:

[2, 3, 4, 5, 6...]
    ^
[2, 4, 5, 6...]
       ^

And so on.

There's no good way to alter a list's length while iterating over it. The best you can do is something like this:

numbers = [n for n in numbers if n >= 20]

or this, for in-place alteration (the thing in parens is a generator expression, which is implicitly converted into a tuple before slice-assignment):

numbers[:] = (n for n in numbers if n >= 20)

If you want to perform an operation on `n` before removing it, one trick you could try is this:

for i, n in enumerate(numbers):
    if n < 20:
        print("do something")
        numbers[i] = None
numbers = [n for n in numbers if n is not None]

Problem

I've got this piece of code: ``` numbers = list(range(1, 50)) for i in numbers: if i < 20: numbers.remove(i) print(numbers) ``` But, the result I'm getting is: `[2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49]` Of course, I'm expecting the numbers below 20 to not appear in the results. Looks like I'm doing something wrong with the remove.

Original source

Related problems