确定单元格二维列表的邻居

发布于 2024-08-08 19:19:09 字数 401 浏览 5 评论 0原文

我有一个列表列表,类似于

[[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。

现在我意识到,我可以这样做暴力攻击检查每个值 la:

[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]

但这很简单,我想我可以通过看到一些更优雅的方法来了解更多信息。

I have a list of lists, something like

[[1, 2, 3,],[4, 5, 6,],[7, 8, 9]].

Represented graphically as:

1 2 3
4 5 6
7 8 9

I'm looking for an elegant approach to check the value of neighbours of a cell, horizontally, vertically and diagonally. For instance, the neighbours of [0][2] are [0][1], [1][1] and [1][2] or the numbers 2, 5, 6.

Now I realise, I could just do a bruteforce attack checking every value a la:

[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]

But thats easy, and I figured I can learn more by seeing some more elegant approaches.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(17

梦忆晨望 2024-08-15 19:19:10

姆...

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:])

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:])
梦幻的味道 2024-08-15 19:19:10
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
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
紧拥背影 2024-08-15 19:19:10

如果有人对选择直接(非对角)邻居的替代方法感到好奇,请看这里:

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))]

If someone is curious about alternative way to pick direct (non-diagonal) neighbors, here you go:

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))]
不…忘初心 2024-08-15 19:19:10

没有更干净的方法可以做到这一点。如果你真的想要你可以创建一个函数:

def top(matrix, x, y):
     try:
         return matrix[x][y - 1];
     except IndexError:
         return None

There's no cleaner way to do this. If you really want you could create a function:

def top(matrix, x, y):
     try:
         return matrix[x][y - 1];
     except IndexError:
         return None
只涨不跌 2024-08-15 19:19:10

这是你的列表:

(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) 位于边缘,只需对邻居的坐标再施加一项限制 - 矩阵大小。

Here is your list:

(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)

So the horizontal neighbors of (x, y) are (x +/- 1, y).

The vertical neighbors are (x, y +/- 1).

Diagonal neighbors are (x +/- 1, y +/- 1).

These rules apply for an infinite matrix.
To make sure the neighbors fit into a finite matrix, if the initial (x, y) is at the edge, just apply one more restriction to the coordinates of neighbors - the matrix size.

我要还你自由 2024-08-15 19:19:10
>>> 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]

我不知道它对你来说有多优雅,但它似乎无需任何硬编码即可工作。

>>> 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]

I don't know how elegant it seems to you, but it seems to work w/o any hard-coding.

苄①跕圉湢 2024-08-15 19:19:10

这会生成所有索引:

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]

This generates all indices:

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]
何以笙箫默 2024-08-15 19:19:10

如果 lambda 使您感到畏惧,那么您​​就是了。但是 lambda 使您的代码看起来干净。@johniek_comp 有一个非常干净的解决方案 TBH

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))

If lambdas daunt you here you are .But lambdas make your code look clean.@johniek_comp has a very clean solution TBH

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))
寄离 2024-08-15 19:19:10

受到之前答案之一的启发。

您可以使用 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)]

Inspired by one of the previous answers.

You can use min() and max() functions to shorten the calculations:

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)]
ら栖息 2024-08-15 19:19:10

感谢 @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 []

Thank you to @JS_is_bad for a great hint about the neighbors. Here is the running code for this problem:

    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 []
爱的故事 2024-08-15 19:19:10

受到约翰尼克的回答的启发,我的解决方案也检查了边界。

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

Inspired by johniek's answer here is my solution which also checks for boundaries.

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
世态炎凉 2024-08-15 19:19:10
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
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
卷耳 2024-08-15 19:19:10
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
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
琉璃繁缕 2024-08-15 19:19:10
# 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]
# 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]
在梵高的星空下 2024-08-15 19:19:10

也许您正在检查数独框。如果盒子是 nxn 并且当前单元格是 (x,y) 开始检查:

startingRow = x / n * n;
startingCol = y/ n * n

maybe you are checking a sudoku box. If the box is n x n and current cell is (x,y) start checking:

startingRow = x / n * n;
startingCol = y/ n * n
习ぎ惯性依靠 2024-08-15 19:19:09
# 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)]

我不知道这是否被认为是干净的,但是这一行通过迭代它们并丢弃任何边缘情况为您提供了所有邻居。

# 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)]

I don't know if this is considered clean, but this one-liner gives you all neighbors by iterating over them and discarding any edge cases.

余生一个溪 2024-08-15 19:19:09

假设您有一个方阵:

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 表达式 和 < a href="https://docs.python.org/2/tutorial/controlflow.html#unpacking-argument-lists" rel="noreferrer">明星运算符,功能相当漂亮但仍然足够可读。

给定矩阵大小为 3,您可以(如果需要)将邻居收集到列表中:

>>> list(neighbours((2,2)))
[(1, 1), (1, 2), (2, 1)]

该函数的作用可以如下所示:

函数可视化

Assuming you have a square matrix:

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

Using itertools.product and thanks to Python's yield expression and star operator, the function is pretty dry but still readable enough.

Given a matrix size of 3, you can then (if needed) collect the neighbours in a list:

>>> list(neighbours((2,2)))
[(1, 1), (1, 2), (2, 1)]

What the function does can be visualized as follows:

Function visualization

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文