Welcome toVigges Developer Community-Open, Learning,Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.0k views
in Technique[技术] by (71.8m points)

algorithm - How to find neighbors in a multi-dimensional array?

Let's say we have a N-dimensional array A with the dimension N determined at runtime.

I wonder whether there is any way I can find all neighboring elements in A of certain element A[a1][a2]...[aN] without invoking recursive methods.

In a 2-dimensional case it is easy to write 8 neighboring elements of A[i][j]: A[i-1][j-1], A[i-1][j], A[i-1][j+1], A[i][j-1], A[i][j+1], A[i+1][j-1], A[i+1][j], A[i+1][j+1], or code with a simple for loop. However, the same task on a higher-dimensional array does seem to need more tedious effort.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

You just need to iterate over the Cartesian power of the set {-1, 0, 1} to N to form the indices relative to the current one, being careful to discard the all-zeros combination (which would correspond to the current element):

algorithm neighbors(N : positive integer,
                    index : N-tuple of integers)
    neighbors_list := empty list
    for relative_index in cartesian_power({-1, 0, 1}, N) do
        if not (relative_index is all zeros then)
            new_index := [index[i] + relative_index[i] for i in 1..N]
            neighbors_list := append(neighbors_list, new_index)
        end
    loop
    return neighbors_list

Note that this can be lazily evaluated when possible and necessary. The Cartesian power can as well be implemented in a non-recursive manner:

algorithm cartesian_power(s : set, N : positive integer)
    result := list(empty list)
    repeat N times
        result_step= empty list
        for res in result do
            for elem in s do
                new_res := append(res, s)
                result_step := append(result_step, new_res)
            loop
        loop
       result := result_step
    loop
    return result

You could also lazy-evaluate this algorithm, although it's a bit more complicated because you would have to generate the elements created in the last iteration of the outermost loop.

These algorithms do not take into account things like index bounds or other constraints, so you may need to add additional logic depending on the case, but the core idea is the same.

Here is an example implementation as a Python generator:

from itertools import product

def neighbors(index):
    N = len(index)
    for relative_index in product((-1, 0, 1), repeat=N):
        if not all(i == 0 for i in relative_index):
            yield tuple(i + i_rel for i, i_rel in zip(index, relative_index))

print(list(neighbors((1, 2)))
>>> [(0, 1), (0, 2), (0, 3), (1, 1), (1, 3), (2, 1), (2, 2), (2, 3)]

print(list(neighbors((1, 2, 3)))
>>> [(0, 1, 2),
 (0, 1, 3),
 (0, 1, 4),
 (0, 2, 2),
 (0, 2, 3),
 (0, 2, 4),
 (0, 3, 2),
 (0, 3, 3),
 (0, 3, 4),
 (1, 1, 2),
 (1, 1, 3),
 (1, 1, 4),
 (1, 2, 2),
 (1, 2, 4),
 (1, 3, 2),
 (1, 3, 3),
 (1, 3, 4),
 (2, 1, 2),
 (2, 1, 3),
 (2, 1, 4),
 (2, 2, 2),
 (2, 2, 3),
 (2, 2, 4),
 (2, 3, 2),
 (2, 3, 3),
 (2, 3, 4)]

Obviously I am cheating here because I am using a Python builtin function to compute the Cartesian power. However, if you go to the documentation of itertools.product you will see a Python implementation of the algorithm I wrote above.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to Vigges Developer Community for programmer and developer-Open, Learning and Share

2.1m questions

2.1m answers

63 comments

56.6k users

...