How to access the adjacent cells of each elements of matrix in python?
Question:
Here two cells are considered adjacent if they share a boundary.
For example :
A = 5 6 4
2 1 3
7 9 8
Here adjacent elements to index 0,0 is at index [0,1] and [1,0] and for index 1,1 the adjacent elements are at index [0,1],[1,0],[2,1] and [1,2].
Answers:
Supposed you have m
xn
matrix, and you want to find the adjacent indices of the cell (i
, j
):
def get_adjacent_indices(i, j, m, n):
adjacent_indices = []
if i > 0:
adjacent_indices.append((i-1,j))
if i+1 < m:
adjacent_indices.append((i+1,j))
if j > 0:
adjacent_indices.append((i,j-1))
if j+1 < n:
adjacent_indices.append((i,j+1))
return adjacent_indices
To also check for diagonals, regarding what Casper Dijkstrao asked, I usually write some code like this:
def adj_finder(matrix, position):
adj = []
for dx in range(-1, 2):
for dy in range(-1, 2):
rangeX = range(0, matrix.shape[0]) # X bounds
rangeY = range(0, matrix.shape[1]) # Y bounds
(newX, newY) = (position[0]+dx, position[1]+dy) # adjacent cell
if (newX in rangeX) and (newY in rangeY) and (dx, dy) != (0, 0):
adj.append((newX, newY))
return adj
The function gets the matrix
argument to extract the size of its row and column (I use numpy
, so matrix.shape
returns (row_size, column_size)
tuple).
It also gets the current cell as pointer
argument (it’s like (X,Y)
).
Then It generate adjacent cells, and if they were legit (1. they were not out of the bound, and 2. not identical to reference position), it adds them to adjacent list, adj
.
I’d like to emphasize that using the above algorithm, you can easily obtain neighbors in farther distances as well. Just modify the range in the for loops, like this:
for v in range(0-distance, 1+distance):
for h in range(0-distance, 1+distance):
...
Where distance
is the maximum distance of adjacent you want to let in.
This will be another way – prob. involve some math tricks or regarded more concise (if you’re more math-inclined) :
def neighbours(grid, r, c):
vals = sum((row[c -(c>0): c+2]
for row in grid[r -(r>0):r+2]), [])
vals.remove(grid[r][c]) # rm itself.
return vals
grid = [[1, 5, 4, 9],
[2, 8, 3, 8],
[6, 3, 6, 3],
[7, 4, 7, 1]]
Outputs: (all items are in order)
print(f' {neighbours(grid, 2, 2)} ') # [8, 3, 8, 3, 3, 4, 7, 1]
print(f' {neighbours(grid, 0, 0)} ') # [5, 2, 8]
print(f' {neighbours(grid, 1, 1)} ') # [[1, 5, 4, 2, 3, 6, 3, 6]
Here two cells are considered adjacent if they share a boundary.
For example :
A = 5 6 4
2 1 3
7 9 8
Here adjacent elements to index 0,0 is at index [0,1] and [1,0] and for index 1,1 the adjacent elements are at index [0,1],[1,0],[2,1] and [1,2].
Supposed you have m
xn
matrix, and you want to find the adjacent indices of the cell (i
, j
):
def get_adjacent_indices(i, j, m, n):
adjacent_indices = []
if i > 0:
adjacent_indices.append((i-1,j))
if i+1 < m:
adjacent_indices.append((i+1,j))
if j > 0:
adjacent_indices.append((i,j-1))
if j+1 < n:
adjacent_indices.append((i,j+1))
return adjacent_indices
To also check for diagonals, regarding what Casper Dijkstrao asked, I usually write some code like this:
def adj_finder(matrix, position):
adj = []
for dx in range(-1, 2):
for dy in range(-1, 2):
rangeX = range(0, matrix.shape[0]) # X bounds
rangeY = range(0, matrix.shape[1]) # Y bounds
(newX, newY) = (position[0]+dx, position[1]+dy) # adjacent cell
if (newX in rangeX) and (newY in rangeY) and (dx, dy) != (0, 0):
adj.append((newX, newY))
return adj
The function gets the
matrix
argument to extract the size of its row and column (I usenumpy
, somatrix.shape
returns(row_size, column_size)
tuple).It also gets the current cell as
pointer
argument (it’s like(X,Y)
).Then It generate adjacent cells, and if they were legit (1. they were not out of the bound, and 2. not identical to reference position), it adds them to adjacent list,
adj
.
I’d like to emphasize that using the above algorithm, you can easily obtain neighbors in farther distances as well. Just modify the range in the for loops, like this:
for v in range(0-distance, 1+distance):
for h in range(0-distance, 1+distance):
...
Where
distance
is the maximum distance of adjacent you want to let in.
This will be another way – prob. involve some math tricks or regarded more concise (if you’re more math-inclined) :
def neighbours(grid, r, c):
vals = sum((row[c -(c>0): c+2]
for row in grid[r -(r>0):r+2]), [])
vals.remove(grid[r][c]) # rm itself.
return vals
grid = [[1, 5, 4, 9],
[2, 8, 3, 8],
[6, 3, 6, 3],
[7, 4, 7, 1]]
Outputs: (all items are in order)
print(f' {neighbours(grid, 2, 2)} ') # [8, 3, 8, 3, 3, 4, 7, 1]
print(f' {neighbours(grid, 0, 0)} ') # [5, 2, 8]
print(f' {neighbours(grid, 1, 1)} ') # [[1, 5, 4, 2, 3, 6, 3, 6]