0

I have an list containing other lists like this:

self.trails = [
  [10, 50],
  [20, 30],
  [100,50],
  [25, 75]
]

And I'm trying to loop through it and delete any items if they are too close of some other coordinates:

def distance_real(x1,y1,x2,y2):
    return Math.sqrt( (x1-x2)*(x1-x2) + (y1-y2)*(y1-y2) )

class MathClass
   trails = [
      [10, 50],
      [20, 30],
      [100,50],
      [25, 75]
   ]

   def run(self):
      pointx = 10
      pointy = 15

      while 1:
         for trail in self.trails:
             d = distance_real(pointx, pointy, trail[0], trail[1])
                 if d < 5:
                    self.trails.remove(trail)
         time.sleep( 1.0/30 )

The code doesn't remove all trails that are supposed to. After adding a for loop and looped it five times it successfully removed them.

Any ideas? Using the for loop is not efficient in my case since trails contains a couple thousand entities and the code has to run within a couple of milliseconds.

Globala
  • 103
  • 2
  • 14

2 Answers2

2

Do the operations on a tmp list first and then assign trails to it at the end

def distance_real(x1,y1,x2,y2):
    return Math.sqrt( (x1-x2)*(x1-x2) + (y1-y2)*(y1-y2) )

class MathClass
   trails = [
      [10, 50],
      [20, 30],
      [100,50],
      [25, 75]
   ]

   def run(self):
       pointx = 10
       pointy = 15

       tmp = []
       while 1:
           for trail in self.trails:
               d = distance_real(pointx, pointy, trail[0], trail[1])
               if d >= 5:
                   tmp.append(trail)
           self.trails = tmp
           time.sleep( 1.0/30 )
farghal
  • 281
  • 1
  • 5
1

You're modifying a list while iterating. Try converting it to a tuple first like so:

for trail in tuple(self.trails):
    d = distance_real(pointx, pointy, trail[0], trail[1])
    if d < 5:
        self.trails.remove(trail)

or in one line:

self.trails = [
    x for x in self.trails if
    distance_real(pointx, pointy, trail[0], trail[1]) >= 5]
Bharel
  • 23,672
  • 5
  • 40
  • 80