在 2D JavaScript 数组周围添加填充

Posted

技术标签:

【中文标题】在 2D JavaScript 数组周围添加填充【英文标题】:Adding padding around a 2D JavaScript array 【发布时间】:2022-01-23 06:47:03 【问题描述】:

我正在尝试创建一个用零填充二维数组的函数。我做了以下功能:

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

如果我只调用一次,该函数可以正常工作,但如果我调用它两次,就像在这个例子中一样,我会得到下表:

我的函数有一个意外结果,它为 2 行添加了额外的零。有谁知道为什么会这样?

【问题讨论】:

【参考方案1】:

第一次在 same 数组a 的顶部和底部填充。这意味着同一个数组第二次被填充(左右)两次。

通过复制避免添加 same 数组。

变化:

arr.push(a)

到:

arr.push([...a])

【讨论】:

【参考方案2】:

@trincot 的回答很好,我只是想提出这种语法:

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

    return [a, ...arr.map(el => [0, ...el, 0]), a]


const arr = addPadding(addPadding([[1,2],[3,4]]))

arr.forEach(el => document.write(el + '<br>'))

【讨论】:

【参考方案3】:

为了让你的函数是幂等的,你需要检查你的数组是否已经被填充。您可以通过检查所有“外边缘”是否为 0 来做到这一点。您可以认为这是一个“框架”:

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

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>

【讨论】:

以上是关于在 2D JavaScript 数组周围添加填充的主要内容,如果未能解决你的问题,请参考以下文章

如何通过检查局部最大值是否通过检查周围的所有数字是否小于它来遍历2D数组? [关闭]

如何在 WebView 周围添加填充

在 swift 3 中在圆形图像视图周围添加填充?

检查二维数组中相邻方块的值

创建并填充2D数组

用随机列表中的 2 个值填充 2D 数组(2048 游戏)