在javascript 2d矩阵中查找连接的组件

时间:2017-11-09 18:35:14

标签: javascript arrays

我的数组可能如下所示:

var array = [
    [1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
    [0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
    [0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
    [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
    [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
    [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
    [0,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,0,0]
    [0,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,0,0]
    [0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0]
    [0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0]
    [0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0]
    [0,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,0,0]
    [0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0]
    [0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0]
    [0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0]
    [0,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,0,0]
    [0,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,1,0,0,0]
    [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0]
    [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0]
    [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
]

我想找到这个2d矩阵中的所有连通分量,比如中间的'E'字符,(我们称之为SQUARE)在左上角和另一个“square”在右下角用不同的数字标记它们以得到这样的结果:

var result = [
        [1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
        [0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
        [0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
        [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
        [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
        [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
        [0,0,0,0,0,0,2,2,2,2,2,2,2,0,0,0,0,0,0,0]
        [0,0,0,0,0,0,2,2,2,2,2,2,2,0,0,0,0,0,0,0]
        [0,0,0,0,0,0,2,2,0,0,0,0,0,0,0,0,0,0,0,0]
        [0,0,0,0,0,0,2,2,0,0,0,0,0,0,0,0,0,0,0,0]
        [0,0,0,0,0,0,2,2,0,0,0,0,0,0,0,0,0,0,0,0]
        [0,0,0,0,0,0,2,2,2,2,2,2,2,0,0,0,0,0,0,0]
        [0,0,0,0,0,0,2,2,0,0,0,0,0,0,0,0,0,0,0,0]
        [0,0,0,0,0,0,2,2,0,0,0,0,0,0,0,0,0,0,0,0]
        [0,0,0,0,0,0,2,2,0,0,0,0,0,0,0,0,0,0,0,0]
        [0,0,0,0,0,0,2,2,2,2,2,2,2,0,0,0,0,0,0,0]
        [0,0,0,0,0,0,2,2,2,2,2,2,2,0,0,0,3,0,0,0]
        [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,3,0,0]
        [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,3,3,0,0]
        [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
    ]

我的代码绝对运行如下:

var array = [
        [1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
        [0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
        [0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
        [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
        [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
        [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
        [0,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,0,0],
        [0,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,0,0],
        [0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0],
        [0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0],
        [0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0],
        [0,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,0,0],
        [0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0],
        [0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0],
        [0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0],
        [0,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,0,0],
        [0,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,1,0,0,0],
        [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0],
        [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0],
        [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
      ]
      
      
      
      

function find_connected_components(array) {
	var default_value=1;
	function test_connection(array, i, j, value) {
	    if (array[i] && array[i][j] === -1) {
	        array[i][j] = value;
	        test_connection(array, i + 1, j, value);
	        test_connection(array, i, j + 1, value);
	        return true;
	    }
	}
	array.forEach(function (a) {
	    a.forEach(function (b, i, bb) {bb[i] = -b;});
	});
	array.forEach(function (a, i, aa) {
	    a.forEach(function (b, j, bb) {test_connection(aa, i, j, default_value) && default_value++;});
	})
	console.log(array.map(a => [a.join('')]).map(a => [a.join('')]))
}


find_connected_components(array)      

但是 - 现在我的错误出现,直到我从上面旋转我的阵列。所以它看起来像这样:

var error_array = [
    [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
    [0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
    [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
    [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
    [0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0],
    [0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0],
    [0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0],
    [0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0],
    [0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0],
    [0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0],
    [0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0],
    [0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0],
    [0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0],
    [0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0],
    [0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0],
    [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
    [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
    [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
    [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0],
    [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0],  
]

上面 error_array 的结果是完全错误的&我不知道如何解决这个问题。

PS:我没有编辑过ERROR数组代码片段,因为我的问题很长。 Soo请为自己尝试error_array。

我希望有人可以解释如何修复我的代码:)

  

编辑 1:这是error_array

的输出

image

提前感谢一百万人!

问候乔纳斯

2 个答案:

答案 0 :(得分:2)

一个问题:您的test_connection有点像flood fill algorithm,但它只会向右和向下移动。您需要修改您的功能以填充和向左填充。

它适用于第一种情况,因为当仅从左上角向右和向下移动时,可以正确填充“E”形状。但是当翻转“E”时(第二种情况,递归调用不再到达“E”的水平条。

答案 1 :(得分:0)

首先,将1的值更改为-1,因为您需要使用1作为标记。

然后,您可以迭代元素并执行检查,如果它具有标记-1,则将其更改为实际值。继续使用右边和底部的元素。

如果找到了元素,则增加值。



function test(array, i, j, value) {
    if (array[i] && array[i][j] === -1) {
        array[i][j] = value;
        test(array, i -1, j, value);
        test(array, i + 1, j, value);
        test(array, i, j - 1, value);
        test(array, i, j + 1, value);
        return true;
    }
}

var data = [[1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]],
    value = 1;

data.forEach(function (a) {
    a.forEach(function (b, i, bb) {
        bb[i] = -b;
    });
});

data.forEach(function (a, i, aa) {
    a.forEach(function (b, j, bb) {
        test(aa, i, j, value) && value++;
    });
});

document.getElementById('out').innerHTML = data.map(function (a) { return a.join(' '); }).join('\n');

<pre id="out"></pre>
&#13;
&#13;
&#13;