Bottom Page

Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
 Index error using pop in nested loop
#1
Hello. This is my first post, so I hope I'm not screwing this up too badly. I'm trying to get back into Python and coding in general after a 10ish year hiatus by making a snake game.

I'm creating a list of directions and a list of wait times for each snake body segment. When wait is 0 the snake body segments update their direction according accompanying list of directions. This works as intended until I attempt to clear the lists of unnecessary data by calling pop(). I'm assuming what's happening is because the list is being popped during the loop, the next iteration doesn't have the correct ranges, but I can't think of a clean alternative way to clean the list of used data.

Any insight would be appreciated. Thank you!

    def change_direction(self, new_direction):
        if new_direction != self.snake_head.direction:
            self.snake_head.direction = new_direction
            for i in range(len(self.snake_body)):
                self.snake_body[i].wait.append(i+1)
                self.snake_body[i].directions.append(new_direction)

    def traffic_control(self):
        for x in range(len(self.snake_body)):
            for y in range(len(self.snake_body[x].wait)):
                self.snake_body[x].wait[y] -= 1
                if self.snake_body[x].wait[y] == 0:
                    self.snake_body[x].change_direction_body(self.snake_body[x].directions[y])
                    #list.pop(self.snake_body[x].wait, y)
                    #list.pop(self.snake_body[x].directions, y)
Quote
#2
First, you should loop directly over things, not over their indexes:

def traffic_control(self):
    for segment in self.snake_body:
        for timer in segement.wait:
            ...
Second, you just don't want to mess with a list while iterating over it. I think the best solution would be to build a new list. So start with new_body = [], and then if you want to keep it, new_body.append(segment).
Craig "Ichabod" O'Brien - xenomind.com
I wish you happiness.
Recommended Tutorials: BBCode, functions, classes, text adventures

Quote
#3
Thanks for the reply. I attempted to swap around some of my code to fit that convention of just iterating through the objects themselves, but I think I made some structural errors in how my program fits together and I'm not sure if the situation can be salvaged. In the example above, I can't get around needing the index to retrieve the specific directions for the snake body. I tried an enumeration as a kind of hack, but that failed and I'm not quite sure why.
    def traffic_control(self):
        for segment in self.snake_body:
            for index, timer in enumerate(segment.wait):
                timer -= 1
                if timer == 0:
                    segment.change_direction_body(segment.directions[index])
I did manage to find a really hacky way to clear the used data from my lists, but I'm really not happy with it. I again couldn't find an alternative to using indexes as a way to sort through the data that needed cleaning, so this is what the function ended up looking like. I hope this isn't too painful to look at.

    def traffic_control(self):
        dirtyx = []
        dirtyy = []
        for x in range(len(self.snake_body)):
            for y in range(len(self.snake_body[x].wait)):
                self.snake_body[x].wait[y] -= 1
                if self.snake_body[x].wait[y] == 0:
                    self.snake_body[x].change_direction_body(self.snake_body[x].directions[y])
                    dirtyx.append(x)
                    dirtyy.append(y)
        for item in range(len(dirtyx)):
            list.pop(self.snake_body[dirtyx[item]].wait, dirtyy[item])
            list.pop(self.snake_body[dirtyx[item]].directions, dirtyy[item])
Quote
#4
I was thinking something more like this:

def traffic_control(self):
    for segment self.snake_body:
        new_wait, new_directions = [], []
        for timer, direction in zip(segment.wait, segment.directions):
            timer -= 1
            if timer:
                new_wait.append(timer)
                new_directions.append(direction)
            else:
                segment.change_direction_body(direction)
        segment.wait = new_wait
        segment.directions = new_directions
I think that should work and is a lot cleaner. I would also think about the underlying data structures. Can they be redesigned to work more smoothly with what needs to be done to them?
Craig "Ichabod" O'Brien - xenomind.com
I wish you happiness.
Recommended Tutorials: BBCode, functions, classes, text adventures

Quote

Top Page

Possibly Related Threads...
Thread Author Replies Views Last Post
  ValueError: Index contains duplicate entries, cannot reshape” error when I try to use Smiling29 11 351 Oct-26-2019, 09:52 PM
Last Post: Smiling29
  openpyxl nested for loop help rmrten 3 197 Oct-16-2019, 03:11 PM
Last Post: stullis
  nested for loop dilemma YoungGrassHopper 9 330 Sep-13-2019, 03:56 AM
Last Post: jsira2003
  nested for loop dilemma 2 YoungGrassHopper 12 389 Sep-12-2019, 02:06 PM
Last Post: YoungGrassHopper
  Get all values of for loop with an index BollerwagenIng 2 310 Aug-09-2019, 07:58 AM
Last Post: BollerwagenIng
  Nested while loop problem + turtle DreamingInsanity 3 340 Jul-06-2019, 02:01 PM
Last Post: DreamingInsanity
  Com Error with macro within for loop due to creating new workbook in the loop Lastwizzle 0 217 May-18-2019, 09:29 PM
Last Post: Lastwizzle
  I getting Index error after numerous tries priyanshu 3 345 Apr-21-2019, 05:15 PM
Last Post: ichabod801
  Nested for loop strange problem mcva 2 397 Mar-16-2019, 12:53 PM
Last Post: mcva
  Index Error ErnestTBass 5 488 Feb-18-2019, 10:02 PM
Last Post: ErnestTBass

Forum Jump:


Users browsing this thread: 1 Guest(s)