简体   繁体   中英

Find connected components in javascript 2d matrix

My array maybe looks like this:

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

I'd like to find all connected components in this 2d matrix like the 'E'-character in the middle, the (lets call it SQUARE) in the left corner above and the other "square" in the right bottom and mark them all with different numbers to get a result like this:

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

My code that works absolutely well looks like this:

 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) 

But- now my error appears until I rotate my array from above. SO that it looks like this:

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

The result for the error_array above is completely wrong & I have no clue how to fix this.

PS: I haven't edited a ERROR-array code snippet because my question would be to long. Soo please try the error_array for your own.

And I hope somebody can explain how to fix my code:)

Edit 1 : This is the output for the error_array

图片

Thanks a million in advance!

Greetings jonas

One problem: your test_connection is kind of like a flood fill algorithm , but it only moves to right and down. You need to modify your function to fill up and to the left as well.

It works for the first case pretty well because the "E" shape can be filled correctly when only moving right and down from the top-left point. But when the "E" is flipped (your second case, the recursive call no longer reaches the horizontal bars of the "E".

First, change the value of 1 to -1 , because you need to use 1 as flag.

Then you could iterate the elements and perform a check and if it has the flag -1 , then change it to the actual value. Proceed with the element of the right and bottom.

If an element was found, increment value.

 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> 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM