How to get continue to work properly?

The following code is used:

for a in range(len(coins)):
      coins[a].updatepos()
      if coins[a].collide(plyr):
        coins.pop(a)
        plyr.score += 1
        continue

      if coins[a].collide(plyr2):
        coins.pop(a)
        plyr2.score += 1
        continue

If you’ll notice, after each if statement I’ve included continue to skip the iteration once part of the array is removed, so the program doesn’t keep trying to read a nonexistent list item. However, the console still returns this:

Traceback (most recent call last):
  File "main.py", line 294, in <module>
    coins[a].updatepos()
IndexError: list index out of range

I can’t include links in my posts, so just go to my profile @arn5891 and look for a program labeled “very original title”.

It seems like the error is occurring because the length of the array is changing while you are iterating over it.

tl;dr: Use filter() instead:

def manage_coin(coin):
  coin.updatepos()
  if coin.collide(plyr):
    plyr.score += 1
    return False # Returning false in the filter predicate removes it from the array
  if coin.collide(plyr2):
    plyr2.score += 1
    return False
  return True # Keep it in the array by default

coins = list(filter(manage_coin, coins))

Why does this happen?

This code aims to remove the second element from the array

arr = [1, 2, 3]
for a in range(len(arr)):
  print(f"Index: {a}  Element: {arr[a]}")
  if a == 1:
    print("Removing")
    arr.pop(a)
    continue 

This prints out:

Index: 0  Element: 1
Index: 1  Element: 2
Removing
Traceback (most recent call last):
  File "test1.py", line 3, in <module>
    print(f"Index: {a}  Element: {arr[a]}")
IndexError: list index out of range

After the first iteration, a = 0 and the array is unchanged
After the second iteration, a = 1 and arr is now [1, 2]
Now during the 3rd iteration, a = 2. However, when the program tries to access arr[2] it crashes because arr does not have three elements

Example Code Updated to use `filter()`
arr = [1, 2, 3]
def handle_item(item):
    print(f"Element: {item}")
    if item == 2: # We use 2 because item is a reference to the actual list item, not the index
        print("Removing")
        return False
    return True
print(list(filter(handle_item, arr)))

Output:

Element: 1
Element: 2
Removing
Element: 3
[1, 3]

I hope this helps!

4 Likes

It works with splicing the array, but does filter() permanently wipe the list for the remainder of the program? After I reset the coins array to the value of another called coinslist, the program still doesn’t display the coin images according to the array, which should have several objects in it. The weird thing is that the program prints both arrays as the same. It’s probably an error on my part.

1 Like

That’s weird! filter() doesn’t wipe the list passed into it. It returns a new copy of the list (more specifically, an iterator which we then turn into a list).

Example
arr = [1, 2, 3]
def handle_item(item):
    print(f"Element: {item}")
    if item == 2: # We use 2 because item is a reference to the actual list item, not the index
        print("Removing")
        return False
    return True
print(list(filter(handle_item, arr)))
print(arr)
Element: 1
Element: 2
Removing
Element: 3
[1, 3]
[1, 2, 3]

I had a look at your code and it seems like the coinlist array is never modified, which makes this even stranger. I also can’t figure out how to play the game, so instructions would be helpful for debugging :wink:

I have barely any Pygame experience, but I suspect the problem may be that the same array of coins (coinlist) is being assigned to coins every time the player advances a level. I could very well be wrong, but try creating new coins in nextlevel

One other thing I noticed is that you are calling filter once for every element in the coins array:

for a in range(len(coins)):
      coins = list(filter(manage,coins))
      print("coins array:")
      print(len(coins))
      print("coinlist array:")

This won’t have any visible effects (apart from a slight performance improvement) but you can remove the for loop

2 Likes

Thanks. The coinlist array is never supposed to be modified- it’s a sort of “save file” for the coins. Every level, the coins array should “reset” so there’s a consistent number of coins per level. I do that by setting coins to coinlist every time nextlevel is called. You’re suggesting I just directly append new coin objects to the main coins array rather than reassigning coins to coinlist, correct?

btw, WASD/Arrow keys to play, get to the green pipe thing to progress, don’t let the brown things get there before you do

1 Like

It’s weird, it used to work but I’m getting this:

  File "main.py", line 329, in <module>
    coins = list(filter(manage, coins))
  File "main.py", line 185, in manage
    c.updatepos()
  File "main.py", line 81, in updatepos
    grid[self.y][self.x] = self.id
IndexError: list index out of range
1 Like

Earlier I’d posted that the solution didn’t work- in reality, I just forgot to make coins a global variable in nextlevel. Sorry for the inconvenience, your post has been re-selected as a solution.

1 Like

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.