2010-12-21 73 views
1

基本上它应该采用一组坐标并返回其邻居的坐标列表。然而,当它击中的位置:为什么这段代码返回一个列表索引错误?

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 

回答

4

您可以从列表中迭代索引,然后继续从列表中删除元素。最终你会遇到一个不再存在的索引。改用列表理解来过滤。

result = [entry for entry in result if entry[0] >= 0 and 
    entry[0] < board.dimensions and entry[1] >= 0 and 
    entry[1] < board.dimensions] 
+0

我应该用这段代码替换整个for循环吗?我在理解语法方面有点麻烦。 – mmmeff 2010-12-21 05:18:49

+0

是的,它取代了整个for循环。 http://docs.python.org/tutorial/datastructures.html#list-comprehensions – 2010-12-21 05:19:40

+0

非常感谢您的救命!此外,链接到pydocs页面是一个真棒触摸。祝你有愉快的一天。 – mmmeff 2010-12-21 05:20:17

2

在其降低result大小for循环,你如雨后春笋般冒出的元素。然而,i仍然会从0到4.

2

如果弹出一个元素,它不再在列表中 - 但是您的索引不会移动,所以它现在指向下一个元素。假设你弹出两个元素...你的列表大小之后将是2,但for循环仍将尝试去4.

+0

我不能相信我错过了。非常感谢你。任何想法如何解决它? – mmmeff 2010-12-21 05:14:32

0

正如其他人所说,其余元素的索引在您删除来自列表中间的元素。为了避免出现问题,你可以处理来自最后一个索引的元素先:

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

现在,在当前元素被删除,只对已经处理的元素指标变化。由于这些元素已经被处理并且不需要再次被访问,因此它们的索引是否不再有效并不重要。

1
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

避免这种板外测试的规范方法是在板的边缘有一个或两个行/列的缓冲区。除了通常的“空白”或者哪一方拥有广场上的哪种类型的棋子,特殊的“无效”代码以外,董事会的职位也会有。这通常会与一个董事会代表一起作为一维数组。

例如,国际象棋将使用大小为120的数组(10列×12行)。为了迎合骑士的需要,你需要2的边距......每一端有2排,但你只需要一个垂直边距,因为它可以共享。

E.g.

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 
1

使用列表理解删除无效点。例如:

result = [coords for coords in result 
      if all(0 <= c < board.dimension for c in coords)]