javascript:快速查找数组中的连接组件(寻找加速/替代方式)

时间:2017-12-04 20:07:02

标签: javascript arrays regex algorithm matrix

我有一个矩阵( 1d数组,x& y-ax ),如下所示:

var matrix=[
'00000000000000000000000000000000000000000000000000000000000000000000111111111',
'11111100000000000000000000001000000000000000000000000000000000000000000001111',
'00000000000000000000000000000000001000000000000000000000000000000000000000011',
'11111000000000000000000000000000000000000001111110000000000000000000000000001',
'11111000000000000111000000000000000000111111000000000000000000000000000000000',
'00000000000111111111111100000000000000111111000000000000000000000000000000000',
'00000000000000000110000000000000000000111111000000000000000000010000000000000',
'00000000000000000000000000000001111111000000000000000000000000000000000000000',
'00000100000000000000000000000000000000000000000000000000000000000010000000000',
'00000010010000000000000000000000000000111111110000000000000000000000000000000',
'00000000000000000000000000000000000000000000000000000000000000000000000000000',
'00000000000000000000000000000000000000000000000000000000000000100000000000000',
'00000000000000000000000000000000000000000000000000000100000000000000000000000'
]

我喜欢找到' 1' -characters的所有连接组并提取他们所有的位置以获得这样的结果:

[{"0": [[68,0],[69,0],[70,0],[71,0],[72,0],[73,0],[73,1],[74,1],[75,1],[75,2],[76,2],[76,3],[76,1],[76,0],[75,0],[74,0]],"1": [[0,1],[1,1],[2,1],[3,1],[4,1],[5,1]],"2": [[28,1]],"3": [[34,2]],"4": [[0,3],[0,4],[1,4],[2,4],[3,4],[4,4],[4,3],[3,3],[2,3],[1,3]],"5": [[43,3],[43,4],[43,5],[43,6],[42,6],[42,5],[42,4],[41,4],[41,5],[41,6],[40,6],[40,5],[40,4],[39,4],[39,5],[39,6],[38,6],[38,5],[38,4],[44,3],[45,3],[46,3],[47,3],[48,3]],"6": [[17,4],[17,5],[17,6],[18,6],[18,5],[19,5],[20,5],[21,5],[22,5],[23,5],[19,4],[18,4],[16,5],[15,5],[14,5],[13,5],[12,5],[11,5]],"7": [[63,6]],"8": [[31,7],[32,7],[33,7],[34,7],[35,7],[36,7],[37,7]],"9": [[5,8]],"10": [[66,8]],"11": [[6,9]],"12": [[9,9]],"13": [[38,9],[39,9],[40,9],[41,9],[42,9],[43,9],[44,9],[45,9]],"14": [[62,11]],"15": [[53,12]]}]



我已经开发了某种 flood fill algorithm ,它与上面的矩阵一起工作得很好。

  

但必须有一种更有效率的方式。快速查找更大矩阵中的连通组件(例如,大10甚至100倍)。    - >我的想法也许这个结果也可以用某种正则表达式结合javascript代码来实现,但我绝对不知道如何编写这个,所以我希望有个好主意加快我的小算法,以便我可以避免溢出错误



var matrix=[
'00000000000000000000000000000000000000000000000000000000000000000000111111111',
'11111100000000000000000000001000000000000000000000000000000000000000000001111',
'00000000000000000000000000000000001000000000000000000000000000000000000000011',
'11111000000000000000000000000000000000000001111110000000000000000000000000001',
'11111000000000000111000000000000000000111111000000000000000000000000000000000',
'00000000000111111111111100000000000000111111000000000000000000000000000000000',
'00000000000000000110000000000000000000111111000000000000000000010000000000000',
'00000000000000000000000000000001111111000000000000000000000000000000000000000',
'00000100000000000000000000000000000000000000000000000000000000000010000000000',
'00000010010000000000000000000000000000111111110000000000000000000000000000000',
'00000000000000000000000000000000000000000000000000000000000000000000000000000',
'00000000000000000000000000000000000000000000000000000000000000100000000000000',
'00000000000000000000000000000000000000000000000000000100000000000000000000000'
]

Array.prototype.extract_components_positions = function(offset) {
	var array = this.map(item => item.split('')).map(str => Array.from(str, Number)),
		default_value = 0,
		result_object = {}

	function test_connection(array, i, j) {
		if (array[i] && array[i][j] === -1) {
			if (!result_object[default_value]) result_object[default_value] = [];
			result_object[default_value].push([j, i]);
			array[i][j] = 1;
			for (var k = offset; k > 0; k--) {
				test_connection(array, i + k, j); // left - right
				test_connection(array, i, j + k); // top - bottom
				test_connection(array, i - k, j); // right - left
				test_connection(array, i, j - k); // bottom - top
			}
			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++
		})
	})
	return [result_object];
}



var result = matrix.extract_components_positions(1);
console.log((result))

.as-console-wrapper { max-height: 100% !important; top: 0; }




  

编辑1.0 BTW如果算法只能连接更大的组件(例如最少5个连接字符组)

,那也没那么糟糕

1 个答案:

答案 0 :(得分:0)

代码

这是我想出的方法。我确信它可以被优化,但我觉得这至少是朝着正确方向迈出的一大步。

我也从以下答案中获取信息并应用它。

var matrix=[
'00000000000000000000000000000000000000000000000000000000000000000000111111111',
'11111100000000000000000000001000000000000000000000000000000000000000000001111',
'00000000000000000000000000000000001000000000000000000000000000000000000000011',
'11111000000000000000000000000000000000000001111110000000000000000000000000001',
'11111000000000000111000000000000000000111111000000000000000000000000000000000',
'00000000000111111111111100000000000000111111000000000000000000000000000000000',
'00000000000000000110000000000000000000111111000000000000000000010000000000000',
'00000000000000000000000000000001111111000000000000000000000000000000000000000',
'00000100000000000000000000000000000000000000000000000000000000000010000000000',
'00000010010000000000000000000000000000111111110000000000000000000000000000000',
'00000000000000000000000000000000000000000000000000000000000000000000000000000',
'00000000000000000000000000000000000000000000000000000000000000100000000000000',
'00000000000000000000000000000000000000000000000000000100000000000000000000000'
]

var results = [];

function charPos(str, char) {
  return str
         .split("")
         .map(function (c, i) { if (c == char) return i; })
         .filter(function (v) { return v >= 0; });
}

matrix.forEach(function(s, i) {
  var p = charPos(s, '1');
  results[i] = [];
  matrix.forEach(function(s2, i2) {
    var p2;
    if((p2 = charPos(s2, '1').filter((n) => p.includes(n))).length) {
      p2.forEach(function(v) {
        if(JSON.stringify(results).indexOf(JSON.stringify([v, i2])) === -1)
          results[i].push([v, i2]);
      });
    }
  });
});

console.log(results.filter(v => v.length > 0));