繁体   English   中英

从表示为一维数组的另一个二维数组中提取二维数组

[英]extract 2D array from another 2D array represented as a 1D array

所以如果我有一个二维数组,比如

const array = [
            [1, 2, 3, 4, 5],
            [9, 8, 7, 6, 5],
            [1, 8, 3, 6, 5],
            [9, 8, 7, 6, 5],
            [1, 8, 3, 6, 5],
            [1, 2, 3, 4, 5]
          ];

对于问题的重点,它可以是任何大小,正方形或非正方形。

我想从中提取 3x3 数组,例如在 1,1 处,即const sub = [[8, 7, 6], [8, 3, 6], [8, 7, 6]] 到目前为止一切顺利 - 我可以做到这一点。 但是,我正在展平 2D 数组,以便将其表示为 1D 数组(关于原因的长篇故事),即

const array = [1, 2, 3, 4, 5, 9, 8, 7, 6, 5, 1, 8, 3, 6, 5, 9, 8, 7, 6, 5, 1, 8, 3, 6, 5, 1, 2, 3, 4, 5];

我想要做的是从中提取相同(或任何)3x3 数组,但它表示为一维数组,所以我会返回[8, 7, 6, 8, 3, 6, 8, 7, 6]

几乎到了那里,但是我犯了一个错误,即只使用 9x9 的数组并总是提取 3x3 子集,这意味着我的解决方案只适用于特定情况,而且我越盯着我的解决方案,我就越无法解决通用解决方案会是什么样子。

我的解决方案:

const extractSubsetFrom1D = (array, subHeight, subWidth, startRow, startCol) => {
    const kWH = subWidth * subHeight
    const subset = array.slice(((((kWH - 2) * startRow) + startCol) * kWH), ((((kWH - 2) * startRow) + startCol) * kWH) + kWH)
    return subset
}

在我的情况下, subHeightsubWidth总是分别等于 3,并且由于数组本身总是 9x9,我相信我不小心偶然发现了针对该特定情况的解决方案,因为它们很好地分割成彼此。

要清楚我的解决方案对于所提供的数组的startRow = 1 startCol = 0将失败(它适用于startRow = 0场景

我并不完全清楚您是如何实现当前实施的,但我至少可以说:

  • ✅ 您正确确定了要返回的子网格数组的大小( kWH
  • ❌您错误地认为您可以将子网格分割为原始一维数组的一个连续部分
  • 🟠 第一个元素的计算看似正确但实际上是错误的(可能是因为前面的错误)

(y,x)i

让我们从头开始,逐步打造一个不错的单排。

在二维数组中,您可以通过以下方式获取单元格的值:

cellValue = grid2d[y][x]

将其展平后,您需要执行以下操作:

cellValue = grid1d[y * GRID_WIDTH + x]

y * GRID_WIDTH将您带到右行的开头,而+ x将您带到右列。

如您所见,在查询特定单元格之前,您需要知道原始网格的大小。 这意味着您的提取函数需要一个参数来传递原始宽度(或者,如果保证网格是正方形的,您可以执行Math.sqrt(array.length)

每行一个切片

让我们使用这个数学来找到从 3x3 源网格中提取的 (1,1) 处的 2x2 子网格的索引:

0  1  2
3 [4][5]
6 [7][8]

如您所见,结果索引为[4,5,7,8] 没有办法直接从源数组中切出这些索引,因为我们不想包含6

相反,我们可以使用嵌套循环来跳过行之间的间隙:

 const to1d = (x, y, w) => y * w + x; const extractSubGrid1D = (grid, gridWidth, x, y, w, h) => { const yTop = y; const yBottom = y + h const xLeft = x; const xRight = x + w; const subgrid = []; for (let y = yTop; y < yBottom; y += 1) { for (let x = xLeft; x < xRight; x += 1) { const index = to1d(x, y, gridWidth); subgrid.push(grid[index]); } } return subgrid; } const originalGrid = [ 0, 1, 2, 3, 4, 5, 6, 7, 8 ]; console.log( extractSubGrid1D(originalGrid, 3, 1, 1, 2, 2) )

一旦你对逻辑有了感觉,就可以随意重构。

另一种方式

要从 1d 索引到 2d 坐标,您可以执行以下操作:

x = i % w
y = Math.floor(i / w)

应用此逻辑,您还可以像这样填充子网格:

  • 创建一个合适大小的新数组
  • 对于它的每个索引,确定原始网格的(x, y)坐标
  • 将该坐标转换回索引以查询原始网格

 const to1d = (x, y, w) => y * w + x; const extractSubGrid1D = (grid, gridWidth, x, y, w, h) => Array.from( { length: w * h }, (_, i) => grid[to1d(x + i % w, y + Math.floor(i / w), gridWidth)] ) const originalGrid = [ 0, 1, 2, 3, 4, 5, 6, 7, 8 ]; console.log( extractSubGrid1D(originalGrid, 3, 1, 1, 2, 2) )

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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