简体   繁体   中英

Adding padding around a 2D JavaScript array

I am attempting to create a function that pads a 2D array with zeros. I have made the following function:

function addPadding(arr){
    var a = new Array(arr.length + 2).fill(0)

    //left and right padding
    arr.forEach(el => {
        el.push(0)
        el.unshift(0)
    })

    //top padding
    arr.unshift(a)

    //bottom padding
    arr.push(a)

    return arr;
}

console.table(addPadding(addPadding([[1,2],[3,4]])));

The function works fine if I only call it once, but if I call it twice, like in this example, I get the following table:

在此处输入图像描述

My function has an unintended result, it has added extra zeroes for 2 rows. Does anyone know why this is happening?

The first time you are padding at top and bottom the same array a . This means the second time that same array gets padded (left & right) twice.

Avoid adding the same array by taking a copy.

Change:

arr.push(a)

to:

arr.push([...a])

Good answer from @trincot, I just wanted to propose this syntax:

 function addPadding(arr) { const a = new Array(arr.length + 2).fill(0) return [a, ...arr.map(el => [0, ...el, 0]), a] } console.log(addPadding(addPadding([[1,2],[3,4]])))

In order for your function to be idempotent, you need to check if your array has already been padded. You could do this by checking to see if all the "outer edges" are 0. You could think of this aa "frame":

const getFrame = (arr) => {
    const topEdge = arr[0];
    const bottomEdge = arr[arr.length-1];
    const leftEdge = arr.map(row => row[0]);
    const rightEdge = arr.map(row => row[row.length-1]);
    return [topEdge, bottomEdge, leftEdge, rightEdge];
};

Now we simply walk the frame to see if all the values are zero:

const isAllZeros = (frame) => {
    return frame.every(edge => {
        return edge.every(n => {
            return (n === 0);
        });
    });
};

Now we know when to pad or not to pad. So we write the function that pads:

const padArray = (arr) => {
    let newArray = [];
    let firstAndLastRow = new Array(arr[0].length+2).fill(0);
    newArray.push(firstAndLastRow);
    arr.forEach(oldRow => {
      let newRow = Array.from(oldRow);
      newRow.unshift(0);
      newRow.push(0);
      newArray.push(newRow);
    });
    newArray.push(firstAndLastRow);
    return newArray; 
};

 const getFrame = (arr) => { const topEdge = arr[0]; const bottomEdge = arr[arr.length-1]; const leftEdge = arr.map(row => row[0]); const rightEdge = arr.map(row => row[row.length-1]); return [topEdge, bottomEdge, leftEdge, rightEdge]; }; const isAllZeros = (frame) => { return frame.every(edge => { return edge.every(n => { return (n == 0); }); }); }; const padArray = (arr) => { let newArray = []; let firstAndLastRow = new Array(arr[0].length+2).fill(0); newArray.push(firstAndLastRow); arr.forEach(oldRow => { let newRow = Array.from(oldRow); newRow.unshift(0); newRow.push(0); newArray.push(newRow); }); newArray.push(firstAndLastRow); return newArray; }; // debugging stuff const rowsEl = document.getElementById('rows'); const colsEl = document.getElementById('cols'); const generateButton = document.getElementById('gen'); const padButton = document.getElementById('pad'); const vis = document.getElementById('vis'); const dbg = document.getElementById('dbg'); let arr2d = []; generateButton.addEventListener('click', () => { const rows = rowsEl.valueAsNumber; const cols = colsEl.valueAsNumber; arr2d = []; for (let row=0; row<rows; row++) { let thisRow = []; for (let col=0; col<cols; col++) { thisRow.push(Math.floor(Math.random()*10)); } arr2d.push(thisRow); } showArray(arr2d); }); padButton.addEventListener('click', () => { const frame = getFrame(arr2d); const isPadded = isAllZeros(frame); if (;isPadded) { arr2d = padArray(arr2d); } showArray(arr2d); }); const showArray = (arr) => { let txt = ''. arr.forEach(row => { txt += "\n" + `${row;join(" ")}`; }). vis;innerText = txt; const frame = getFrame(arr2d); const isPadded = isAllZeros(frame); };
 <form name=f id=f> <table> <tr> <td><label for=rows>rows</label></td> <td><input type=number name=rows id=rows value=3 /></td> </tr> <tr> <td><label for=cols>cols</label></td> <td><input type=number name=cols id=cols value=3 /></td> </tr> <tr> <td><button id=gen type=button>generate</button></td> <td><button id=pad type=button>pad</button></td> </tr> </table> </form> <pre id="vis"></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