Почему этот код возвращает ошибку индекса списка? - PullRequest
1 голос
/ 21 декабря 2010

В основном он должен принимать набор координат и возвращать список координат своих соседей. Однако, когда он попадает сюда:

if result[i][0] < 0 or result[i][0] >= board.dimensions:
    result.pop(i)

когда i равно 2, это дает мне ошибку вне индекса. Я могу заставить его распечатать результат [2] [0], но в операторе if он выдает ошибки. Почему это происходит?

def neighborGen(row,col,board):
    """
    returns lists of coords of neighbors, in order of up, down, left, right
    """

    result = []
    result.append([row-1 , col])
    result.append([row+1 , col])
    result.append([row , col-1])
    result.append([row , col+1])

     #prune off invalid neighbors (such as (0,-1), etc etc)
     for i in range(len(result)): 
        if result[i][0] < 0 or result[i][0] >= board.dimensions:
            result.pop(i)
        if result[i][1] < 0 or result[i][1] >= board.dimensions:
            result.pop(i)

    return result 

Ответы [ 7 ]

4 голосов
/ 21 декабря 2010

Вы получаете индексы для перебора из списка, а затем вы продолжаете удалять элементы из списка. В конце концов вы попадете в индекс, который больше не существует. Вместо этого используйте фильтрацию списка.

result = [entry for entry in result if entry[0] >= 0 and
  entry[0] < board.dimensions and entry[1] >= 0 and
  entry[1] < board.dimensions]
2 голосов
/ 21 декабря 2010

Если вы выталкиваете элемент, его больше нет в списке - но ваш индекс не перемещается, поэтому теперь он указывает на следующий элемент.Скажем, вы вытолкнули два элемента ... ваш размер списка после этого будет равен 2, но цикл for все еще будет пытаться перейти к 4.

2 голосов
/ 21 декабря 2010

Во время цикла for появляются элементы, размер которых уменьшается на result.Тем не менее, i будет по-прежнему идти от 0 до 4.

1 голос
/ 21 декабря 2010

Используйте понимание списка, чтобы удалить недействительные точки.Например:

result = [coords for coords in result
          if all(0 <= c < board.dimension for c in coords)]
1 голос
/ 21 декабря 2010
def neighborGen(row,col,board):
    """
    returns lists of coords of neighbors, in order of up, down, left, right
    """

    return [
        x for x in (
            [row-1 , col], [row+1 , col], [row , col-1], [row , col+1]
        ) 
        if x[0] >= 0 and x[0] < board.dimensions and
        x[1] >= 0 and x[1] < board.dimensions
    ]
0 голосов
/ 21 декабря 2010

Канонический способ избежать такого рода внепланового тестирования - это иметь буферную зону из одной или двух строк / столбцов по краям платы. Позиции доски будут иметь, как и обычные значения «пусто» или какой стороне принадлежит квадрат, с каким типом фигуры, специальный «недействительный» код. Обычно это связано с представлением на плате в виде одномерного массива.

Например, в шахматах будет использоваться массив размером 120 (10 столбцов х 12 строк). Вам нужно поле 2, чтобы обслуживать рыцарей ... 2 ряда на каждом конце, но вам нужно только одно вертикальное поле, так как оно может быть общим.

* 1005 Е.Г. *

KNIGHT_DELTAS = (-21, -19, -12, -8, 8, 12, 19, 21)
# I have a knight at "currpos"; what are its options?
for delta in KNIGHT_DELTAS:
    newpos = currpos + delta
    target = board[newpos]
    if target & EMPTY:
        can_move_to(newpos)
    elif target & OTHER_TEAM:
        can_capture(at=newpos, captured_piece=target & PIECE_VALUE)
    else:
        # Either off the board or occupied by MY_TEAM.
        # Notice that we didn't even need to test explicitly for "off the board".
        pass
0 голосов
/ 21 декабря 2010

Как уже говорили другие, индексы оставшихся элементов изменяются при удалении элементов из середины списка.Чтобы избежать проблем, вы можете обрабатывать элементы от последнего индекса к первому:

for i in range(len(result)-1, -1, -1): 
   ...

Теперь, когда текущий элемент удален, изменяются только индексы для уже обработанных элементов.Поскольку эти элементы уже обработаны и больше не нуждаются в доступе, не имеет значения, являются ли их индексы недействительными.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...