且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

如何在多维数组中查找邻居?

更新时间:2022-06-25 09:27:36

您只需要迭代一下的{-1,0,1}集合中的笛卡尔幂 N 以形成相对于当前索引的索引,请小心丢弃全零组合(这将与当前元素相对应):

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.

这里是一个示例作为Python生成器实现:

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

很明显,我在这里作弊是因为我正在使用Python内置函数来计算笛卡尔乘方。但是,如果您转到 itertools.product 的文档a>您将看到我上面编写的算法的Python实现。

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.