vaindil
vaindil

Reputation: 7854

unexpected behavior when altering a list that I'm iterating through

I'm relatively new to Python and I cannot for the life of me figure out what's going on here. Python is skipping every other number when using for to loop over a list, but only after a certain number of elements in. This is part of a larger project I'm working on, but this snippet of code illustrates it.

The code works properly until 7, at which point it begins skipping every other number. I know not to edit a list I'm in the process of iterating over, so I'm avoiding that, but the for isn't even calling some of them. What do I need to do to get it to loop through each number rather than every other? Why is it doing this?

Code:

import math

i1 = 60
l1 = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 49, 53, 59]
l3 = l1

print(l1)
for a in l1:
    print(a)
    if a > math.floor(math.sqrt(i1)):
        print("REMOVED: " + str(a))
        l3.remove(a)

print(l3)

Output:

[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 49, 53, 59]
2
3
5
7
11
REMOVED: 11
17
REMOVED: 17
23
REMOVED: 23
31
REMOVED: 31
41
REMOVED: 41
47
REMOVED: 47
53
REMOVED: 53
[2, 3, 5, 7, 13, 19, 29, 37, 43, 49, 59]

Upvotes: 2

Views: 86

Answers (3)

Mario Rossi
Mario Rossi

Reputation: 7799

You don't remove elements from a collection while iterating it. l1 and l3 are referencing the same list. Perhaps what you intended is:

    l3= list(l1)

This will take a copy.

Upvotes: 1

arshajii
arshajii

Reputation: 129507

l3 = l1

Now, l3 and l1 refer to the same list. Calling remove() on one will effect the other as well. So, when you call l3.remove(a) while iterating over l1, an item in l1 (!) is removed, all the subsequent elements are shifted down, the loop iterates to the next element, and an item is consequently skipped.

For example, imagine that we're looping through the following list and we remove b:

-----------------
| a | b | c | d |
-----------------
      ^ (we're on b)

-----------------
| a |   | c | d |
-----------------
      ^ (remove b)

-------------
| a | c | d |
-------------
      ^ (shift elements down)

-------------
| a | c | d |
-------------
          ^ (step)

Notice that we skipped c.

Perhaps you meant

l3 = list(l1)  # create a new, independent list

Upvotes: 6

Cameron Sparr
Cameron Sparr

Reputation: 3981

l3 and l1 are pointing to the same list, if you want them to be unique, use l3 = l1[:]

Upvotes: 6

Related Questions