Nihl
Nihl

Reputation: 587

`for`-loop on python `sortedlist` does not iterate over all elements

I'm trying to go through a list, which is growing during the loop. For larger lists, I encounter a strange behavior, the iteration stops before going through all elements:

from blist import sortedlist

# for-loop
l = sortedlist(range(400))
for x in l:
    print(x)
    if x % 10 == 0:
        l.add(max(l) + 1)

print('last element:', l[-1])

# while-loop
l = sortedlist(range(400))
k = 0
while True:
    try:
        print(l[k])
        if l[k] % 10 == 0:
            l.add(max(l) + 1)
        k = k + 1
    except IndexError:
        break

print('last element:', l[-1])

Results:

.
.
.
430
431
last element: 443

.
.
.
443
444
last element: 444

This does not occur for a normal list. And the "while-loop" goes through all elements as I want. I suppose sortedlist are stored as trees structures, and somehow it does not play well with modifiying a list during a loop, but if anyone has more insight on this (and/or a clearer/better way to get the same behavior than the "while-loop")

Note that it is not a critical portion performant-wise, so I don't mind the log(n) access cost in the "while-loop" case.

Upvotes: 0

Views: 1188

Answers (1)

Dyrborg
Dyrborg

Reputation: 877

ORGINAL ANSWER

The reason is very simple. When you create a foreach loop over a collection, the loop retains a local copy of the information of the list it iterates through. This means it only iterates the length of your original lists (with no regards to any modifications).

The while loop just checks whether a condition is true for each iteration and does not keep a local copy of your list information.

Modified answer

Based on your comment I tried to reproduce it but was unsuccessful. However this seem to produce what you want:

l = sorted(range(400))
for x in l:
    print x
    if x%10 == 0:
        l.append(max(l)+1)
        
print str(l[-1])

Upvotes: 2

Related Questions