在下面的方法中,我已经组装了一个元组列表,同时试图确保没有任何值小于零。下面的方法首先采用一个块并使用它以1为增量计算相邻块的坐标,然后继续删除其坐标小于零的块。我的问题在于第二阶段,因为如果我输入一个坐标为(0,0)的块:(0,-1)和(-1,0),它就不会删除两个坐标。
代码如下:
def get_block_neighbors(self, block):
neighbor_list = []
neighbor_list.append((block.x,block.y+1))
neighbor_list.append((block.x+1,block.y+1))
neighbor_list.append((block.x+1,block.y))
neighbor_list.append((block.x+1,block.y-1))
neighbor_list.append((block.x,block.y-1))
neighbor_list.append((block.x-1,block.y-1))
neighbor_list.append((block.x-1,block.y))
neighbor_list.append((block.x-1,block.y+1))
for item in neighbor_list: #each tuple item in the list
if item[0] < 0 or item[1] < 0:
print item
neighbor_list.remove(item)
print neighbor_list
get_block_neighbors(Block(Point(0,0),"green"))
我得到以下输出:
(1, -1)
(-1, -1)
(-1, 1)
[(0, 1), (1, 1), (1, 0), (0, -1), (-1, 0)]
这里,前三行是我要删除的元组的打印输出,而最后一行是我组装的元组列表。如您所见,最后两个元组的至少一个坐标具有负值。理想情况下,我想要这个:
(1, -1)
(-1, -1)
(-1, 1)
(0, -1)
(-1, 0)
[(0, 1), (1, 1), (1, 0)]
奇怪的是,当我删除/注释掉行neighbor_list.remove(item)
时,我在某种意义上更接近我需要的位置,因为打印输出中的方法包含我想要的两个元组除去。但是,当然,执行此操作的一个缺点是我不再从此列表中删除任何目标元组。
对此的任何帮助都将非常感激,我真的希望我的疏忽不是非常明显的。在旁注中,我觉得应该有一种方法来组合这个列表,同时能够放弃一个删除阶段,这就是我在解决上面的代码之前开始编写这个方法的方法。谢谢!
答案 0 :(得分:3)
问题是您在迭代该列表的同时从列表中删除项目。列表迭代是通过索引(在幕后)发生的,所以这不会像你期望的那样工作,因为当删除它们的前辈时会跳过一些值。
要避免此问题,您可以使用切片迭代列表的副本:
for item in neighbor_list[:]:
或者,更好的是,使用列表推导来构建新列表而不是修改旧列表:
new_list = [(x, y) for x, y in neighbor_list if x >= 0 and y >= 0]
答案 1 :(得分:1)
您不应该从正在迭代的列表中删除项目。首先复制列表,然后迭代它。
答案 2 :(得分:1)
问题在于你正在删除列表的元素,同时你正在迭代它。如果您只是创建一个删除了元素的新列表,那就更简单了:
[item for item in neighbor_list if item[0] >= 0 and item[1] >= 0]
答案 3 :(得分:1)
首先制作一份清单:
for item in neighbor_list[:]: #each tuple item in the list
if item[0] < 0 or item[1] < 0:
print item
neighbor_list.remove(item)
print neighbor_list
答案 4 :(得分:0)
周围更容易:
def get_block_neighbors(self, block):
neighbor_list = []
neighbor_list.append((block.x,block.y+1))
neighbor_list.append((block.x+1,block.y+1))
neighbor_list.append((block.x+1,block.y))
if block.y > 0:
neighbor_list.append((block.x+1,block.y-1))
neighbor_list.append((block.x,block.y-1))
if block.x > 0:
neighbor_list.append((block.x-1,block.y-1))
if block.x > 0:
neighbor_list.append((block.x-1,block.y))
neighbor_list.append((block.x-1,block.y+1))
return neighbor_list
答案 5 :(得分:0)
这是一个示例,显示了一些看起来像是试图从列表中过滤某些数字的代码
>>> L = range(10)
>>> for x in L:
... print x, L
... if x in (4,5,6,7):
... L.remove(x)
...
0 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
1 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
2 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
3 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
4 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
6 [0, 1, 2, 3, 5, 6, 7, 8, 9]
8 [0, 1, 2, 3, 5, 7, 8, 9]
9 [0, 1, 2, 3, 5, 7, 8, 9]
在迭代列表时删除项目通常是个坏主意。
这是获取邻居列表的更简单方法。它完全不需要.remove
def get_block_neighbors(self, block):
x = block.x
y = block.y
xrange = (-1, 0, 1)[x<1:]
yrange = (-1, 0, 1)[y<1:]
return [(x + dx,y + dy) for dx in xrange for dy in yrange if dx or dy]