I'm trying to delete elements from a list with .remove()
and a for loop, but the for loop is comparing against a value that doesn't exist, and throwing an error when it is the last element.
This is what I'm trying to do:
print(positions)
for n in nk:
if n in nQ:
print(n)
positions.remove(n)
print(positions)
nk
and nQ
are both lists, and I want to delete the elements of nk
that are in nQ
.
It returns this when it isn't the last element on the list, which is ok:
[1, 5], [0, 5], [0, 4], [0, 3], [1, 3], [2, 3], [2, 4], [2, 5]]
[0, 3]
[[1, 5], [0, 5], [0, 4], [1, 3], [2, 3], [2, 4], [2, 5]]
[1, 3]
[[1, 5], [0, 5], [0, 4], [2, 3], [2, 4], [2, 5]]
[2, 3]
[[1, 5], [0, 5], [0, 4], [2, 4], [2, 5]]
But when it is the last element this happens:
[[2, 7], [4, 7]]
[2, 7]
[[4, 7]]
[2, 6]
Traceback (most recent call last):
File "main.py", line 379, in <module>
print("Black King Moves:", findMovementsFork(board))
File "main.py", line 255, in findMovementsFork
positions.remove(n)
ValueError: list.remove(x): x not in list
Where is the [2, 6]
coming from, and how can I fix it?
CodePudding user response:
You cannot remove elements while iterating over a list.
You could use a list comprehension:
filtered_nk = [e for e in nk if e not in nQ]
CodePudding user response:
The correct way to do this is with a list comprehension:
filtered_ls = [for n in nk if n not in nQ]
This is essentially constructing a new list, including each element in that list that is not in nQ in the same order as the original list.
The reason for this is that Python will attempt to iterate over your entire list, and if you are modifying that list while it is doing so, that list becomes unstable. Consider this 'unrolled' example:
ls = [1, 2, 3]
rem = [2]
# 'rolled' version
for x in ls:
if x in rem:
ls.remove(x)
# 'unrolled' version
idx = 0
x = ls[idx] # x = 1
in_rem = x in rem # in_rem == False
# skip removal
idx = idx 1
x = ls[idx] # x = 2
in_rem = x in rem # in_rem == False
ls.remove(x) # ls = [1, 3]
idx = idx 1
x = ls[idx] # Errors, because len(ls) == 2 now.
This is roughly equivalent to what you're attempting - there is a slight difference, but the above should demonstrate that iterating through a list with a for loop will cause a problem when you simultaneously remove items from it.
The downside to a list comprehension is you're basically constructing a new list, but as it stands it's likely to be as efficient as what you're doing now, except without the errors.