Home > Net >  How do you find the neighbours of an item in a 2D list?
How do you find the neighbours of an item in a 2D list?

Time:05-28

[
[a,b,c,d],
[e,f,g,h],
[i,j,k,l]
]

For example. g is touching b,c,d,f,h,j,k,l and a is touching e,f,b. I tried a method where I made it a big list and did some trash, but it fell apart, tbh. Here's the code if interested:

import math

big_list = []
x= [
["a", "b", "c", "d", "e", "f"],
["g", "h", "i", "j", "k", "l"],
["m", "n", "o", "p", "q", "r"],
["s", "t", "u", "v", "w", "x"],
["y", "z", "1", "2", "3", "4"]
]

#def find_neighbours(num):
for y in x:
    for element in y:
        big_list.append(element)

def find_row(element):
    columns = len(x)
    loc = big_list.index(element)
    exact_row = (loc)/columns
    return(math.floor(exact_row))

def find_column(element):
    row = find_row(element)
    exact_column = x[row]
    return(exact_column)

print(find_column("x"))

The list can be any size and is not always going to be a square.

CodePudding user response:

Find the row and column index of the element. Then, you can define a list of row / column differences to check in order to generate the indices of the neighbors. Finally, you can loop through these differences to find the neighbors.

from itertools import product

board = [
    ['a','b','c','d'],
    ['e','f','g','h'],
    ['i','j','k','l']
]

target = 'a'

DELTAS = [x for x in product((-1, 0, 1), repeat=2) if x != (0, 0)]

for row_idx in range(len(board)):
    for col_idx in range(len(board[0])):
        if board[row_idx][col_idx] == target:
            row = row_idx
            col = col_idx
            break

neighbors = []
for row_delta, col_delta in DELTAS:
    if 0 <= row   row_delta < len(board) and 0 <= col   col_delta < len(board[0]):
        neighbors.append(board[row   row_delta][col   col_delta])

print(neighbors)

This outputs:

['b', 'e', 'f']

CodePudding user response:

This should work

matrix = [
    ["a", "b", "c", "d", "e", "f"],
    ["g", "h", "i", "j", "k", "l"],
    ["m", "n", "o", "p", "q", "r"],
    ["s", "t", "u", "v", "w", "x"],
    ["y", "z", "1", "2", "3", "4"],
]

def find_arround(x: int, y: int, matrix: list):
    # Assuming all rows are the same size
    up, down = -1, 1
    left, right = -1, 1
    up_left = [up, left]
    up_right = [up, right]
    down_left = [down, left]
    down_right = [down, right]

    allowed_horz = filter(lambda d: d   x >= 0 and d   x < len(matrix), [left, right])
    allowed_vert = filter(lambda d: d   y >= 0 and d   y < len(matrix[0]), [up, down])
    allowed_c = filter(
        lambda c: (c[0]   x >= 0 and c[0]   x < len(matrix))
        and (c[1]   y >= 0 and c[1]   y < len(matrix[0])),
        [up_left, up_right, down_left, down_right],
    )

    for neighbour in allowed_horz:
        yield matrix[x   neighbour][y]

    for neighbour in allowed_vert:
        yield matrix[x][y   neighbour]

    for x_nei, y_nei in allowed_c:
        yield matrix[x   x_nei][y   y_nei]

# Some test cases to check for corner cases, no pun intended.
assert set(find_arround(0, 0, matrix)) == {"b", "h", "g"}, "A"
assert set(find_arround(2, 1, matrix)) == {"g", "h", "i", "m", "o", "s", "t", "u"}, "N"
assert set(find_arround(4, 4, matrix)) == {"v", "w", "x", "2", "4"}, "3"
assert set(find_arround(2, 5, matrix)) == {"k", "l", "q", "w", "x"}, "R"

CodePudding user response:

There are basically two steps involved:

  1. Find the indices of the target item (if any).
  2. Determine the indices of the items around it that are valid.

Here's a literal implementation:

m = [['a', 'b', 'c', 'd', 'e', 'f'],
     ['g', 'h', 'i', 'j', 'k', 'l'],
     ['m', 'n', 'o', 'p', 'q', 'r'],
     ['s', 't', 'u', 'v', 'w', 'x'],
     ['y', 'z', '1', '2', '3', '4']]

width = len(m[0])
height = len(m)

target = 'a'
x = None
for y in range(height):
    try:
        x = m[y].index(target)
    except ValueError:
        continue
    else:
        break  # Found

if x is not None:
    print(f'Target {target!r} found in position [{x}, {y}]')
else:
    raise RuntimeError(f'Target {target!r} not found.')

neighbours = []
for j in range(y-1, y 2):
    if -1 < j < height:
        for i in range(x-1, x 2):
            if -1 < i < width and (i, j) != (x, y):
                neighbours.append((i, j))

print('neighbours:', neighbours)

CodePudding user response:

# How do you find the neighbours of an item in a 2D list?

import numpy as np


def neighbors(array, item):
    item_loc = tuple(np.asarray(np.where(array == item)).T[0].tolist())
    s = tuple(np.array(array.shape) - 1)
    n = np.array([-1, 0,  1])
    rows = item_loc[0]   n
    cols = item_loc[1]   n
    neighbor_loc = [
        (x, y) for x in rows for y in cols if (0 <= x <= s[0]) & (0 <= y <= s[1])
    ]
    neighbor_loc.remove(item_loc)
    print(
        f"The neighbors of {item} are {array[tuple(np.transpose(neighbor_loc))].tolist()}."
    )


array = np.array(
    [
        ["a", "b", "c", "d", "e", "f"],
        ["g", "h", "i", "j", "k", "l"],
        ["m", "n", "o", "p", "q", "r"],
        ["s", "t", "u", "v", "w", "x"],
        ["y", "z", "1", "2", "3", "4"],
    ]
)
item = "r"
neighbors(array, item)

First find the location of the item. Use the shape to determine the edges of the array. Determine the rows and columns that have neighbors, but remove any locations that do not exist. Then remove the items location. Finally, retrieve the neighbors.

This code assumes that all items in the array are unique, and that the item being requested exists in the array.

  • Related