Python Forum
Index error using pop in nested loop
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)
Reply
#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
Reply
#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])
Reply
#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
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  pyscript index error while calling input from html form pyscript_dude 2 938 May-21-2023, 08:17 AM
Last Post: snippsat
  Index error help MRsquared 1 738 May-15-2023, 03:28 PM
Last Post: buran
  Big O runtime nested for loop and append yarinsh 4 1,331 Dec-31-2022, 11:50 PM
Last Post: stevendaprano
  Read nested data from JSON - Getting an error marlonbown 5 1,309 Nov-23-2022, 03:51 PM
Last Post: snippsat
  Replace for loop to search index position illmattic 5 1,227 Sep-03-2022, 04:04 PM
Last Post: illmattic
  Nested for loops - help with iterating a variable outside of the main loop dm222 4 1,532 Aug-17-2022, 10:17 PM
Last Post: deanhystad
  I'm getting a String index out of range error debian77 7 2,278 Jun-26-2022, 09:50 AM
Last Post: deanhystad
  For loop index out of bounds armitron121 2 2,617 Feb-08-2022, 04:23 PM
Last Post: armitron121
  Python Error List Index Out of Range abhi1vaishnav 3 2,236 Sep-03-2021, 08:40 PM
Last Post: abhi1vaishnav
  Index error - columns vs non-column Vinny 3 4,848 Aug-09-2021, 04:46 PM
Last Post: snippsat

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020