Определение соседей ячейки двумерного списка - PullRequest
9 голосов
/ 25 октября 2009

У меня есть список списков, что-то вроде

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

Но это легко, и я подумал, что могу узнать больше, увидев более элегантные подходы.

Ответы [ 12 ]

18 голосов
/ 25 октября 2009
# 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)]

Я не знаю, считается ли это чистым, но эта однострочная строка дает всем соседям, перебирая их и отбрасывая любые крайние случаи.

9 голосов
/ 15 мая 2012

мб ...

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:])
6 голосов
/ 18 декабря 2015

Если у вас есть квадратная матрица:

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 * и оператор , функция довольно сухая , но все еще достаточно читабельна .

Учитывая размер матрицы 3, вы можете (при необходимости) собрать соседей в list:

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

То, что делает функция, можно визуализировать следующим образом:

Function visualization

4 голосов
/ 25 октября 2009
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
2 голосов
/ 02 июля 2016

Если кому-то интересно узнать об альтернативном способе выбора прямых (недиагональных) соседей, вот вам:

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))]
2 голосов
/ 25 октября 2009

Нет более чистого способа сделать это. Если вы действительно хотите, вы можете создать функцию:

def top(matrix, x, y):
     try:
         return matrix[x][y - 1];
     except IndexError:
         return None
1 голос
/ 25 октября 2009

Вот ваш список:

(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) находится на краю, просто примените еще одно ограничение к координатам соседей - размер матрицы.

0 голосов
/ 29 мая 2018

Если лямбды вас пугают, вы здесь. Но лямбды делают ваш код чистым. @ 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))
0 голосов
/ 23 марта 2018

Спасибо @ 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 []
0 голосов
/ 25 октября 2009

Может быть, вы проверяете окно судоку. Если поле имеет значение n x n и текущая ячейка (x, y), начните проверку:

startingRow = x / n * n;
startingCol = y/ n * n
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...