确定二维列表中单元格的邻居
我有一个列表,里面又包含了多个列表,像这样:
[[1, 2, 3,],[4, 5, 6,],[7, 8, 9]]
。
用图形表示就是:
1 2 3
4 5 6
7 8 9
我想找一种优雅的方法来检查一个单元格周围的邻居值,包括水平、垂直和对角线的方向。比如说,单元格[0][2]的邻居是[0][1]、[1][1]和[1][2],也就是数字2、5、6。
现在我意识到,我可以用一种简单粗暴的方法,检查每一个值,像这样:
[i-1][j]
[i][j-1]
[i-1][j-1]
[i+1][j]
[i][j+1]
[i+1][j+1]
[i+1][j-1]
[i-1][j+1]
不过这样太简单了,我觉得通过学习一些更优雅的方法可以学到更多东西。
17 个回答
12
mb...
from itertools import product, starmap
x, y = (8, 13)
cells = starmap(lambda a,b: (x+a, y+b), product((0,-1,+1), (0,-1,+1)))
// [(8, 12), (8, 14), (7, 13), (7, 12), (7, 14), (9, 13), (9, 12), (9, 14)]
print(list(cells)[1:])
23
假设你有一个方阵:
from itertools import product
size = 3
def neighbours(cell):
for c in product(*(range(n-1, n+2) for n in cell)):
if c != cell and all(0 <= n < size for n in c):
yield c
这里使用了 itertools.product
,再加上Python的 yield 表达式 和 星号操作符,这个函数写得相当 简洁,但仍然容易理解。
假设这个矩阵的大小是3,你可以(如果需要的话)把邻居的值收集到一个 list
里:
>>> list(neighbours((2,2)))
[(1, 1), (1, 2), (2, 1)]
这个函数的工作原理可以用下面的图来展示:
32
# Size of "board"
X = 10
Y = 10
neighbors = lambda x, y : [(x2, y2) for x2 in range(x-1, x+2)
for y2 in range(y-1, y+2)
if (-1 < x <= X and
-1 < y <= Y and
(x != x2 or y != y2) and
(0 <= x2 <= X) and
(0 <= y2 <= Y))]
>>> print(neighbors(5, 5))
[(4, 4), (4, 5), (4, 6), (5, 4), (5, 6), (6, 4), (6, 5), (6, 6)]
我不太确定这样写算不算干净,但这一行代码可以通过遍历所有邻居,并且忽略一些特殊情况,来获取所有的邻居。