我有一个二维数组,比如说
0 0 0 0 0
0 2 3 4 0
0 9 1 5 0
0 8 7 6 0
0 0 0 0 0
我需要获取与1相邻的所有数字(2、3、4、5、6、7、8、9)。
除了下面这个难看的方法,还有更好的解决方案吗?
topLeft = array[x-1][y-1]
top = array[x][y-1]
topRight = array[x+1][y-1]
# etc
谢谢!
我有一个二维数组,比如说
0 0 0 0 0
0 2 3 4 0
0 9 1 5 0
0 8 7 6 0
0 0 0 0 0
我需要获取与1相邻的所有数字(2、3、4、5、6、7、8、9)。
除了下面这个难看的方法,还有更好的解决方案吗?
topLeft = array[x-1][y-1]
top = array[x][y-1]
topRight = array[x+1][y-1]
# etc
谢谢!
如果不关心顺序,最简洁的方法可能是使用几个循环:
result = new List<int>(8);
for (dx = -1; dx <= 1; ++dx) {
for (dy = -1; dy <= 1; ++dy) {
if (dx != 0 || dy != 0) {
result.Add(array[x + dx][y + dy]);
}
}
}
如果顺序很重要,您可以构建一个以您想要的顺序列出所有(dx,dy)的列表,并对其进行迭代。正如评论中指出的那样,您可能希望添加边界检查。如果顺序不重要,可以这样做:List<int> result = new List<int>(8);
for (int dx = (x > 0 ? -1 : 0); dx <= (x < max_x ? 1 : 0); ++dx)
{
for (int dy = (y > 0 ? -1 : 0); dy <= (y < max_y ? 1 : 0); ++dy)
{
if (dx != 0 || dy != 0)
{
result.Add(array[x + dx][y + dy]);
}
}
}
就我个人而言,循环比原来的代码更加丑陋。
topLeft = array[ x - 1 ][ y - 1 ]
top = array[ x ][ y - 1 ]
topRight = array[ x + 1 ][ y - 1 ]
midLeft = array[ x - 1 ][ y ]
midRight = array[ x + 1 ][ y ]
botLeft = array[ x - 1 ][ y + 1 ]
bot = array[ x ][ y + 1 ]
botRight = array[ x + 1 ][ y + 1 ]
但如果没有明确指定您需要值的内容,那么在不同方向上所做的操作将决定您是否需要将值放入单独的变量中。
对于类似生命游戏的处理,通常更适合使用位模式而不是单独值的数组,并且可以使用累加器和临时变量一次性扫描水平方向上仅三个八个单元格。对于图形卷积,请使用具有3x3内核的现有库。
处理边界的另一种方法是在每个方向上将数组扩展一个单元格。这避免了在卷积代码中出现昂贵的分支。
我会选择为每个方向设置一个(dx, dy)常量列表,像这样:
struct {
int dx;
int dy;
} directions[] = {{-1,-1,},{-1,0,},{-1,1},{0,-1},{0,1},{1,-1},{1,0},{1,1}};
然后您可以使用简单的循环迭代方向:
for (int i = 0; i < 8; i++) {
// use x + directions[i].dx;
// use y + directions[i].dy;
}
当然,您可以使用sizeof(directions) / sizeof(directions[1])
来代替上面的8
。
x
和 y
会是什么?谢谢。 - Unheilig使用 Python 生成器获取给定矩阵中相邻节点。
def gen_adjacent_node(matrix_2d, node=(0,0)):
rows = len(matrix_2d)
columns = len(matrix_2d[0])
for r in [-1, 0, 1]:
for c in [-1, 0, 1]:
if r == c == 0:
continue
# check valid index
if 0 <= node[0]+r < rows and 0 <= node[1]+c < columns:
# print((node[0]+i, node[1]+j))
yield (node[0]+r, node[1]+c)
yield
是Python特定的运算符,您可能还可以包括如何使用/打印此函数的结果的示例? - John Doevector<int> adj;
for (int i = 0; i < 9; i++)
if (i != 4) adj.push_back(array[x + i/3 - 1][y + i%3 - 1]);
这不是非常清晰的解决方案,但非常简短。
max(r-1, 0)
到min(r+1, arr.size-1)
”来迭代行索引,这对我来说更加简洁。def adjacent(arr, r, c)
rows_ndx = arr.each_index.select { |i| (i-r).abs < 2 }
cols_ndx = arr.first.size.times.select { |j| (j-c).abs < 2 }
rows_ndx.each_with_object([]) do |i,a|
cols_ndx.each { |j| a << arr[i][j] unless [i,j] == [r,c] }
end
end
arr = [
[-1, 2, 3, 4],
[-2, 9, 1, 5],
[-3, 8, 7, 6],
[-4, -5, -6, -7]
]
(0..2).each do |i|
(0..3).each do |j|
puts "adjacent to #{arr[i][j]} at r=#{i}, c=#{j} = #{adjacent(arr, i, j)}"
end
end
打印
adjacent to -1 at r=0, c=0 = [2, -2, 9]
adjacent to 2 at r=0, c=1 = [-1, 3, -2, 9, 1]
adjacent to 3 at r=0, c=2 = [2, 4, 9, 1, 5]
adjacent to 4 at r=0, c=3 = [3, 1, 5]
adjacent to -2 at r=1, c=0 = [-1, 2, 9, -3, 8]
adjacent to 9 at r=1, c=1 = [-1, 2, 3, -2, 1, -3, 8, 7]
adjacent to 1 at r=1, c=2 = [2, 3, 4, 9, 5, 8, 7, 6]
adjacent to 5 at r=1, c=3 = [3, 4, 1, 7, 6]
adjacent to -3 at r=2, c=0 = [-2, 9, 8, -4, -5]
adjacent to 8 at r=2, c=1 = [-2, 9, 1, -3, 7, -4, -5, -6]
adjacent to 7 at r=2, c=2 = [9, 1, 5, 8, 6, -5, -6, -7]
adjacent to 6 at r=2, c=3 = [1, 5, 7, -6, -7]
List<int[]> getSurroundingVals(int[][] array, int x, int y) {
List<int[]> surroundingVals = new ArrayList<>();
// Set offset indices to loop around the given cell coords
row_min = Math.max(x - 1, 0);
row_max = Math.min(x + 1, array.length - 1);
col_min = Math.max(y - 1, 0);
col_max = Math.min(y + 1, array[0].length - 1);
// Loop through the surrounding cells and collect the values
for (int i = row_min; i <= row_max; ++i) {
for (int j = col_min; j <= col_max; ++j) {
if (!(i == 0 && j == 0)) {
surroundingVals.add(new int[]{array[x + i][y + j]});
}
}
}
return surroundingVals;
}
#include <iostream>
using namespace std;
bool isValidPos(int i, int j, int n)
{
if (i < 0 || j < 0 || i > n - 1 || j > n - 1)
return 0;
return 1;
}
void adjacentElements(int arr[][3], int i, int j)
{
int n = 3;
// first row
if (isValidPos(i - 1, j - 1, n))
cout << i - 1 << j - 1 << " ";
if (isValidPos(i - 1, j, n))
cout << i - 1 << j << " ";
if (isValidPos(i - 1, j + 1, n))
cout << i - 1 << j + 1 << " ";
// second row
if (isValidPos(i, j - 1, n))
cout << i << j - 1 << " ";
if (isValidPos(i, j + 1, n))
cout << i << j + 1 << " ";
// third row
if (isValidPos(i + 1, j - 1, n))
cout << i + 1 << j - 1 << " ";
if (isValidPos(i + 1, j, n))
cout << i + 1 << j << " ";
if (isValidPos(i + 1, j + 1, n))
cout << i + 1 << j + 1 << " ";
}
int main()
{
int arr[3][3] = {0};
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
cout << i << j << " "
<< " = [ ";
adjacentElements(arr, i, j);
cout << "]" << endl;
}
// cout << endl;
}
}
输出
00 = [ 01 10 11 ]
01 = [ 00 02 10 11 12 ]
02 = [ 01 11 12 ]
10 = [ 00 01 11 20 21 ]
11 = [ 00 01 02 10 12 20 21 22 ]
12 = [ 01 02 11 21 22 ]
20 = [ 10 11 21 ]
21 = [ 10 11 12 20 22 ]
22 = [ 11 12 21 ]