确定细胞二维列表的邻居
- 2025-04-10 09:47:00
- admin 原创
- 21
问题描述:
我有一个列表列表,例如
[[1, 2, 3,],[4, 5, 6,],[7, 8, 9]]
。
图形表示为:
1 2 3
4 5 6
7 8 9
我正在寻找一种优雅的方法来检查单元格水平、垂直和对角线邻居的值。例如,0 的邻居是 0、1 和 1 或数字 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]
但这很容易,而且我认为通过了解一些更优雅的方法来学习更多。
解决方案 1:
# 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)]
我不知道这是否被认为是干净的,但是这一行代码通过迭代它们并丢弃任何边缘情况为您提供了所有邻居。
解决方案 2:
假设你有一个方阵:
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)]
该函数的作用可以直观地表示如下:
解决方案 3:
毫巴……
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:])
解决方案 4:
for x_ in range(max(0,x-1),min(height,x+2)):
for y_ in range(max(0,y-1),min(width,y+2)):
if (x,y)==(x_,y_): continue
# do stuff with the neighbours
>>> a=[[1, 2, 3], [4, 5, 6], [7, 8, 9]]
>>> width=height=3
>>> x,y=0,2
>>> for x_ in range(max(0,x-1),min(height,x+2)):
... for y_ in range(max(0,y-1),min(width,y+2)):
... if (x,y)==(x_,y_): continue
... print a[x_][y_]
...
2
5
6
解决方案 5:
如果有人对选择直接(非对角)邻居的替代方法感到好奇,请看这里:
neighbors = [(x+a[0], y+a[1]) for a in
[(-1,0), (1,0), (0,-1), (0,1)]
if ( (0 <= x+a[0] < w) and (0 <= y+a[1] < h))]
解决方案 6:
没有更简洁的方法可以做到这一点。如果你真的想要,你可以创建一个函数:
def top(matrix, x, y):
try:
return matrix[x][y - 1];
except IndexError:
return None
解决方案 7:
以下是您的清单:
(x - 1, y - 1) (x, y - 1) (x + 1, y - 1)
(x - 1, y) (x, y) (x + 1, y)
(x - 1, y + 1) (x, y + 1) (x + 1, y + 1)
因此 (x, y) 的水平邻居是 (x +/- 1, y)。
垂直邻居是(x,y +/- 1)。
对角线邻居是(x +/- 1,y +/- 1)。
这些规则适用于无限矩阵。为了确保邻居适合有限矩阵,如果初始 (x, y) 位于边缘,只需对邻居的坐标再施加一个限制 - 矩阵大小。
解决方案 8:
>>> import itertools
>>> def sl(lst, i, j):
il, iu = max(0, i-1), min(len(lst)-1, i+1)
jl, ju = max(0, j-1), min(len(lst[0])-1, j+1)
return (il, iu), (jl, ju)
>>> lst = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
>>> tup = 0, 2
>>> [lst[i][j] for i, j in itertools.product(*sl(lst, *tup)) if (i, j) != tup]
[2, 5, 6]
我不知道您觉得它有多么优雅,但它似乎不需要任何硬编码就可以工作。
解决方案 9:
这将生成所有索引:
def neighboring( array ):
nn,mm = len(array), len(array[0])
offset = (0,-1,1) # 0 first so the current cell is the first in the gen
indices = ( (i,j) for i in range(nn) for j in range(mm) )
for i,j in indices:
all_neigh = ( (i+x,j+y) for x in offset for y in offset )
valid = ( (i,j) for i,j in all_neigh if (0<=i<nn) and (0<=j<mm) ) # -1 is a valid index in normal lists, but not here so throw it out
yield valid.next(), valid ## first is the current cell, next are the neightbors
for (x,y), neigh in neighboring( l ):
print l[x][y], [l[x][y] for x,y in neigh]
解决方案 10:
如果 lambdas 让你望而生畏,那就来这里吧。但是 lambdas 会让你的代码看起来很干净。老实说@johniek_comp 有一个非常干净的解决方案
k,l=(2,3)
x = (0,-1,+1)
y = (0,-1,+1)
cell_u = ((k+a,l+b) for a in x for b in y)
print(list(cell_u))
解决方案 11:
受到先前某个答案的启发。
您可以使用 min() 和 max() 函数来缩短计算:
width = 3
height = 3
[(x2, y2) for x2 in range(max(0, x-1), min(width, x+2))
for y2 in range(max(0, y-1), min(height, y+2))
if (x2, y2) != (x, y)]
解决方案 12:
感谢@JS_is_bad提供的关于邻居的精彩提示。以下是此问题的运行代码:
def findNeighbours(l,elem):
#This try is for escaping from unbound error that happens
#when we try to iterate through indices that are not in array
try:
#Iterate through each item of multidimensional array using enumerate
for row,i in enumerate(l):
try:
#Identifying the column index of the givem element
column=i.index(elem)
except ValueError:
continue
x,y=row,column
# hn=list(((x,y+1),(x,y-1))) #horizontal neighbours=(x,y+/-1)
# vn=list(((x+1,y),(x-1,y))) #vertical neighbours=(x+/-1,y)
# dn=list(((x+1,y+1),(x-1,y-1),(x+1,y-1),(x-1,y+1))) #diagonal neighbours=(x+/-1,y+/-1)
#Creating a list with values that are actual neighbors for the extracted index of array
neighbours=[(x,y+1),(x,y-1),(x+1,y),(x-1,y),(x+1,y+1),(x-1,y-1),(x+1,y-1),(x-1,y+1)]
#Creating a universe of indices from given array
index_list=[(i,j) for i in range(len(l)) for j in range(len(l[i]))]
#Looping through index_list and nested loop for neighbours but filter for matched ones
# and extract the value of respective index
return_values=[l[index[0]][index[1]] for index in index_list for neighbour in neighbours if index==neighbour]
return return_values,neighbours
except UnboundLocalError:
return []
解决方案 13:
受到 johniek 的回答的启发,我的解决方案也检查边界。
def get_neighbours(node, grid_map):
row_index, col_index = node
height, width = len(grid_map), len(grid_map[0])
cells = list(starmap(lambda a, b: (row_index + a, col_index + b), product((0, -1, +1), (0, -1, +1))))
cells.pop(0) # do not include original node
cells = list(filter(lambda cell: cell[0] in range(height) and cell[1] in range(width), cells))
return cells
解决方案 14:
def numCells(grid):
x=len(grid)
y=len(grid[0])
c=0
for i in range(x):
for j in range(y):
value_=grid[i][j]
f=1
for i2 in range(max(0,i-1),min(x,i+2)):
for j2 in range(max(0,j-1),min(y,j+2)):
if (i2,j2) != (i,j) and value_<=grid[i2][j2]:
flag=0
break
if flag ==0:
break
else:
c+=1
return c
解决方案 15:
def getNeighbors(matrix: list, point: tuple):
neighbors = []
m = len(matrix)
n = len(matrix[0])
x, y = point
for i in range (x -1, x +2): #prev row to next row
for j in range(y - 1, y +2): #prev column to next col
if (0 <= i < m) and (0 <= j < n):
neighbors.append((i,j))
return neighbors
解决方案 16:
# Get the neighbour elements
from itertools import product
def neighbours(arr, *coordinate):
x, y=coordinate[0], coordinate[1]
row=[i for i in range(x-1,x+2) if 0<=i<len(arr)]
col=[i for i in range(y-1,y+2) if 0<=i<len(arr[0])]
neighbours= set(product(row,col))-{(x,y)}
return [arr[val[0]][val[1]] for val in neighbours]
# Example:
arr=[[1,2,3],[4,5,6],[7,8,9]]
# 1 2 3
# 4 5 6
# 7 8 9
print(neighbours(arr,0,0))
print(neighbours(arr,0,1))
print(neighbours(arr,1,1))
# Output
[2, 4, 5]
[6, 1, 5, 3, 4]
[2, 6, 8, 1, 7, 3, 9, 4]
arr2=[[12,34,12,54],[23,23,11,44],[76,67,87,22],[13,78,45,22],[55,77,33,87]]
# 12 34 12 54
# 23 23 11 44
# 76 67 87 22
# 13 78 45 22
# 55 77 33 87
print(neighbours(arr2,0,0))
print(neighbours(arr2,2,2))
print(neighbours(arr2,4,3))
# Output
[34, 23, 23]
[11, 67, 78, 23, 22, 22, 45, 44]
[45, 22, 33]
解决方案 17:
也许你正在检查一个数独框。如果框是 nxn 且当前单元格是 (x,y),则开始检查:
startingRow = x / n * n;
startingCol = y/ n * n
扫码咨询,免费领取项目管理大礼包!