0

I've the following code snippet. Why do the loop not remove all points from list points, I'm very confused about that. I mean, all points are in the triangle.

print "check whether",points,"are in triangle"
print "p=",points[0]," is in triangle=",isPointInTri(a,b,c,points[0])
print "p=",points[1]," is in triangle=",isPointInTri(a,b,c,points[1])

for p in points:
    if isPointInTri(a,b,c,p):
        points.remove(p)
    print "now, the following points are available", points
print points

This is the output:

check whether [(2, 1), (4, 1)] are in triangle
p= (2, 1)  is in triangle= True
p= (4, 1)  is in triangle= True
now, the following points are available [(4, 1)]
[(4, 1)]

Has anyone an idea?

BartoszKP
  • 34,786
  • 15
  • 102
  • 130
Sam
  • 387
  • 2
  • 9
  • 22

1 Answers1

2

You are modifying the list that you are iterating over. You should never do this. The reason is that the for loop uses something called an iterator, which basically points to a current element in the list, and in each iteration moves to the next one. When the list is being modified the iterator doesn't know about it. When you remove an element, the iterator still points to "the same place in memory" even though the list is shorter now. So it is after the end of the collection and "thinks" it has already passed over all elements.

Try this instead:

points = [p for p in points if not isPointInTri(a,b,c,p)]

There is also a built-in filter function for this:

 points = filter(lambda p: not isPointInTri(a,b,c,p), points)

Also, the simplest fix to use your code literally is to copy the initial list:

for p in points[:]:
    if isPointInTri(a,b,c,p):
        points.remove(p)
    print "now, the following points are available", points
print points

The slicing operator used like this ([:]) will make a copy of points.

BartoszKP
  • 34,786
  • 15
  • 102
  • 130