Multidimensional array fill

前端 未结 2 701
逝去的感伤
逝去的感伤 2021-01-17 01:12

I\'m trying to fill an area in a multidimensional array and not sure on the approach.

For example I have the following array:

var map = [
    [0, 0,          


        
2条回答
  •  借酒劲吻你
    2021-01-17 01:54

    Assuming you're given a starting position and you want to then fill all neighboring values up/down, left/right that contain the same value, you can do something like this:

    var map = [
        [0, 0, 0, 0, 0, 0, 0, 0, 0],
        [0, 2, 2, 2, 2, 2, 2, 0, 0],
        [0, 2, 0, 0, 0, 0, 2, 0, 0],
        [0, 2, 0, 2, 0, 0, 2, 0, 0],
        [0, 2, 0, 0, 2, 0, 2, 0, 0],
        [0, 0, 2, 0, 0, 0, 2, 0, 0],
        [0, 0, 0, 2, 2, 2, 2, 0, 0],
        [0, 0, 0, 0, 0, 0, 0, 0, 0]
    ];
    
    function fill(data, x, y, newValue) {
        // get target value
        var target = data[x][y];
    
        function flow(x,y) {
            // bounds check what we were passed
            if (x >= 0 && x < data.length && y >= 0 && y < data[x].length) {
                if (data[x][y] === target) {
                    data[x][y] = newValue;
                    flow(x-1, y);    // check up
                    flow(x+1, y);    // check down
                    flow(x, y-1);    // check left
                    flow(x, y+1);    // check right
                }
            }
        }
    
        flow(x,y);
    }
    
    fill(map, 2, 2, 1);
    

    Working demo: http://jsfiddle.net/jfriend00/C83AT/


    Here's a version that doesn't use recursion and appears to work with large data sets. Your large test data set wasn't a very interesting test pattern so I wouldn't say this is tested conclusively, but it seems to work on both the small and large data set:

    Large data example: http://jsfiddle.net/jfriend00/8mrhN/

    Small data example: http://jsfiddle.net/jfriend00/BFTub/ (easier to see the result)

    function fill(data, x, y, newValue) {
        // get target value
        var target = data[x][y];
        // maintain list of cells to process
        // put the starting cell in the queue
        var queue = [{x:x, y:y}], item;
    
        while (queue.length) {
            item = queue.shift();
            x = item.x;
            y = item.y;
            if (data[x][y] === target) {
                data[x][y] = newValue;
                // up
                if (x > 0) {
                    queue.push({x:x-1, y:y})
                }
                // down
                if (x + 1 < data.length) {
                    queue.push({x:x+1, y:y})
                }
                // left
                if (y > 0) {
                    queue.push({x:x, y:y-1});
                }
                // right
                if (y + 1 < data[x].length) {
                    queue.push({x:x, y:y+1});
                }
            }
        }
    }
    

    This could be optimized further for performance by testing the value before putting it in the queue and by following a given direction until you find a non-matching value, if required.

提交回复
热议问题