[英]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
}
在我的情况下, subHeight
和subWidth
总是分别等于 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.