获取二维数组中的相邻元素?

时间:2010-01-10 00:19:27

标签: algorithm arrays language-agnostic matrix multidimensional-array

我有一个二维数组,比如说

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

谢谢!

7 个答案:

答案 0 :(得分:22)

如果您不担心订单,最干净的可能是使用几个循环:

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

答案 1 :(得分:12)

我可能会为每个方向寻找一个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

答案 2 :(得分:7)

个人而言,循环比原始循环更难看。

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内核的现有库。

处理边界的另一种方法是在每个方向上将数组扩展一个单元格。这避免了卷积码中昂贵的分支。

答案 3 :(得分:2)

C++中,这可能如下所示:

vector<int> adj;
for (int i = 0; i < 9; i++)
  if (i != 4) adj.push_back(array[x + i/3 - 1][y + i%3 - 1]);

这不是很明确的解决方案,但很短。

答案 4 :(得分:0)

这是一个Ruby解决方案。即使对于不熟悉Ruby的读者,该算法也应该是明显的。请注意我是如何计算要迭代的行和列的(在大多数语言中都会用类似的方式编写)。对我来说,这似乎比使用“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]

答案 5 :(得分:0)

python生成器以获取给定matirx中的相邻节点

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)

答案 6 :(得分:0)

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