Let's say we have a N-dimensional array A with the dimension N determined at runtime.
假设我们有一个N维数组A,其维度N在运行时确定。
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.
我想知道是否有任何方法可以在不调用递归方法的情况下找到某个元素A [a1] [a2] ... [aN]的A中的所有相邻元素。
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.
在二维情况下,很容易写出A [i] [j]的8个相邻元素: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],或带有简单for循环的代码。但是,更高维数组上的相同任务似乎需要更多的繁琐工作。
1 个解决方案
#1
3
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):
您只需要将集合{-1,0,1}的笛卡尔幂迭代到N以形成相对于当前值的索引,小心丢弃全零组合(这将对应于当前元素) :
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:
以下是Python生成器的示例实现:
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.
显然我在这里作弊是因为我使用Python内置函数来计算笛卡尔幂。但是,如果您转到itertools.product的文档,您将看到我在上面编写的算法的Python实现。
#1
3
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):
您只需要将集合{-1,0,1}的笛卡尔幂迭代到N以形成相对于当前值的索引,小心丢弃全零组合(这将对应于当前元素) :
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:
以下是Python生成器的示例实现:
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.
显然我在这里作弊是因为我使用Python内置函数来计算笛卡尔幂。但是,如果您转到itertools.product的文档,您将看到我在上面编写的算法的Python实现。