Python pop function starts over indexing
Question:
I’m trying to remove all instances from a list, for example 9.
I have an ordered list:
num = [1, 2, 3, 4, 5, 6, 7, 8, 9, 9, 9, 9, 9, 10, 11, 12, 13]
arg = 9
I use bisect_left(num, 9)
, this returns 8 (the first 9 in list). bisect_left uses binary search to return the left most index where a specific value would be placed.
from bisect import bisect_left
num = [1, 2, 3, 4, 5, 6, 7, 8, 9, 9, 9, 9, 9, 10, 11, 12, 13]
arg = 9
index = bisect_left(num, arg)
while(True):
if(num[index] == arg):
num.pop(num[index])
print(num)
print(num[index])
print(arg)
else:
break
When I run this code whilst debugging I print the list.
[1, 2, 3, 4, 5, 6, 7, 8, 9, 9, 9, 9, 10, 11, 12, 13]
[1, 2, 3, 4, 5, 6, 7, 8, 9, 9, 9, 10, 11, 12, 13]
[1, 2, 3, 4, 5, 6, 7, 8, 9, 9, 10, 11, 12, 13]
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]
[1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 13]
[1, 2, 3, 4, 5, 6, 7, 8, 9, 12, 13]
[1, 2, 3, 4, 5, 6, 7, 8, 9, 13]
[1, 2, 3, 4, 5, 6, 7, 8, 9]
Of course if I try an do -1 from the index it doesn’t pop anything as it’s looking at the 7th and comparing it to my argument.
When debugging on the 5th increment of the loop it for some reason pops the 9th index instead.
Whilst further debugging I print num[index]
and it prints 9 every time.
I’m receiving the error ‘num.pop(num[index])
IndexError: pop index out of range’
Answers:
list.pop
accepts the index to remove as its argument, not the value.
num.pop(index)
Note that you should change the loop condition to ensure that the index does not go out of bounds. Alternatively, consider using range
instead.
while index < len(num):
Rather than repeatedly modifying the list in situ (pop) you could find the low boundary using bisect_left then the high boundary using bisect_right. Consequently slice the original list in two parts to make a new version. For example:
from bisect import bisect_left, bisect_right
num = [1, 2, 3, 4, 5, 6, 7, 8, 9, 9, 9, 9, 9, 10, 11, 12, 13]
arg = 9
lo = bisect_left(num, arg)
hi = bisect_right(num, arg)
num = num[:lo]+num[hi:]
print(num)
Output:
[1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 12, 13]
Using bisect is a good idea for a sorted list. You could push it to the limit and get the whole range to remove by using both bisect_left and bisect_right:
from bisect import bisect_left,bisect_right
num = [1, 2, 3, 4, 5, 6, 7, 8, 9, 9, 9, 9, 9, 10, 11, 12, 13]
arg = 9
start,end = bisect_left(num,arg),bisect_right(num,arg)
num[start:end] = []
print(num)
[1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 12, 13]
I’m trying to remove all instances from a list, for example 9.
I have an ordered list:
num = [1, 2, 3, 4, 5, 6, 7, 8, 9, 9, 9, 9, 9, 10, 11, 12, 13]
arg = 9
I use bisect_left(num, 9)
, this returns 8 (the first 9 in list). bisect_left uses binary search to return the left most index where a specific value would be placed.
from bisect import bisect_left
num = [1, 2, 3, 4, 5, 6, 7, 8, 9, 9, 9, 9, 9, 10, 11, 12, 13]
arg = 9
index = bisect_left(num, arg)
while(True):
if(num[index] == arg):
num.pop(num[index])
print(num)
print(num[index])
print(arg)
else:
break
When I run this code whilst debugging I print the list.
[1, 2, 3, 4, 5, 6, 7, 8, 9, 9, 9, 9, 10, 11, 12, 13]
[1, 2, 3, 4, 5, 6, 7, 8, 9, 9, 9, 10, 11, 12, 13]
[1, 2, 3, 4, 5, 6, 7, 8, 9, 9, 10, 11, 12, 13]
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]
[1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 13]
[1, 2, 3, 4, 5, 6, 7, 8, 9, 12, 13]
[1, 2, 3, 4, 5, 6, 7, 8, 9, 13]
[1, 2, 3, 4, 5, 6, 7, 8, 9]
Of course if I try an do -1 from the index it doesn’t pop anything as it’s looking at the 7th and comparing it to my argument.
When debugging on the 5th increment of the loop it for some reason pops the 9th index instead.
Whilst further debugging I print num[index]
and it prints 9 every time.
I’m receiving the error ‘num.pop(num[index])
IndexError: pop index out of range’
list.pop
accepts the index to remove as its argument, not the value.
num.pop(index)
Note that you should change the loop condition to ensure that the index does not go out of bounds. Alternatively, consider using range
instead.
while index < len(num):
Rather than repeatedly modifying the list in situ (pop) you could find the low boundary using bisect_left then the high boundary using bisect_right. Consequently slice the original list in two parts to make a new version. For example:
from bisect import bisect_left, bisect_right
num = [1, 2, 3, 4, 5, 6, 7, 8, 9, 9, 9, 9, 9, 10, 11, 12, 13]
arg = 9
lo = bisect_left(num, arg)
hi = bisect_right(num, arg)
num = num[:lo]+num[hi:]
print(num)
Output:
[1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 12, 13]
Using bisect is a good idea for a sorted list. You could push it to the limit and get the whole range to remove by using both bisect_left and bisect_right:
from bisect import bisect_left,bisect_right
num = [1, 2, 3, 4, 5, 6, 7, 8, 9, 9, 9, 9, 9, 10, 11, 12, 13]
arg = 9
start,end = bisect_left(num,arg),bisect_right(num,arg)
num[start:end] = []
print(num)
[1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 12, 13]