The problem is the list l
gets smaller after calling l.remove(value)
, but subscript 'i' still try to index the original l
.
Based on the above analysis, one solution is to keep l
unchanged in the inner loop, the other is to keep the unseen i
reduced along with l
.
# Create new lists to keep `l` unchanged in the inner loop
def method1():
l = [0, 1, 0, 0, 1, 1]
removed= []
while l:
next_l = []
[next_l.append(v) if v <= 0 else removed.append(i) for i, v in enumerate(l)]
l = [x+1 for x in next_l]
return removed
def method2():
l = [0, 1, 0, 0, 1, 1]
removed= []
while l:
num_del = 0 # record number of deletions in the inner loop
for i in range(len(l)):
if l[i-num_del]>0:
l.remove(l[i-num_del])
num_del += 1
# store the index processing order
removed.append(i)
else:
continue
l = [x+1 for x in l]
return removed
assert method1() == method2()
# output [1, 4, 5, 0, 1, 2]
But I guess you expect the result [1, 4, 5, 0, 2, 3]
, i.e., record the processing order with subscript in the original list. If so, try this:
l = [0, 1, 0, 0, 1, 1]
el = list(enumerate(l))
removed = []
bound = 0
while len(removed) != len(l):
removed.extend(list(filter(lambda iv: iv[1] > bound, el)))
el = list(filter(lambda iv: iv[1] <= bound, el))
bound -= 1
removed, _ = zip(*removed)