delete items from a list compared to another list while iterating python

Viewed 53

I am trying to delete an item from a list in a for loop but as the first item gets removed the list goes out of range to be deleted from. I have tried a few different ways of getting around it, but none of them worked. Here is the original code:

availibleMoves = ["TL", "TM", "TR", "CL", "CM", "CR", "BL", "BM", "BR"]
while True:
    print("Please enter the current state of the board in 1D, current move is", move)
    current_board = input("> ")
    board_list = list(current_board)
    if len(board_list) != 9:
        print("Please enter the correct value\n\n")
    else:
        for i in range(0, 9):
            if board_list[i] == "0":
                pass
            else:
                del availibleMoves[i]
        print(availibleMoves)
        break

Any help is appreciated, thanks, sorry if this question is bad but I am in year 10 doing computer science GCSE and this is just a project for fun.

Edit: an example of what I typed in as an input was 100000001

4 Answers

For this usecase I think it would be easier to use a dictionary to store each board position and their values.

if len(current_board) != 9:
    print("Please enter the correct value\n\n")
    continue
board = {i: v for i, v in enumerate(current_board)}

For example, "001002000" becomes:

{0: '0', 1: '0', 2: '1', 3: '0', 4: '0', 5: '2', 6: '0', 7: '0', 8: '0'}

To get the available moves you can loop over the dictionary to find all of the positions that are value '0'

available_moves = [i for i, v in board.items() if v == '0']

Which returns

[0, 1, 3, 4, 6, 7, 8]

If you want to reference this by the string names instead of index values, you can zip the names with the input:

>>> current_board = "001002000"
>>> moves = ["TL", "TM", "TR", "CL", "CM", "CR", "BL", "BM", "BR"]

>>> board = {m: v for m, v in zip(moves, current_board)}
>>> board
{'TL': '0', 'TM': '0', 'TR': '1', 'CL': '0', 'CM': '0', 'CR': '2', 'BL': '0', 'BM': '0', 'BR': '0'}

>>> available_moves = [m for m, v in board.items() if v == '0']
>>> available_moves 
['TL', 'TM', 'CL', 'CM', 'BL', 'BM', 'BR']

You can try to only keep the values that are 1 in your entered board rather than removing the ones with values 0.

This is because every time you remove a value, all the indices after that value also shift back by 1.

...
else:
    ret = [board_list[i] for i in range(9) if board_list[i] == '1']
    break
...

It looks like the problem is that you're shrinking the size of the list by deleting items, but still trying to loop through 9 items. You could try substitute for some other value and then remove them if you really need. Something like this:

        for i in range(0,9):
            if board_list[i] != "0" and i < 9:
                availibleMoves[i] = -1
        while -1 in availibleMoves:
            availibleMoves.remove(-1)

One (horribly unpythonic) way of doing this would be to go through the list backwards:

for i in range(9 - 1, -1, -1):
    if board_list[i] != "0":
        del availibleMoves[i]

However, other suggestions here would be much better.

Related