从一维化的二维数组中提取指定尺寸的子数组
通用一维数组提取指定子数组方案
需求说明
给定一个由任意尺寸二维数组按行优先扁平化得到的一维数组,需要从中提取指定起始位置(startRow, startCol)、指定尺寸(subHeight行 × subWidth列)的子数组,返回一维形式的结果。
示例场景:
- 原二维数组:
const array2D = [ [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] ];
- 扁平化后的一维数组:
const array1D = [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];
- 提取要求:从
(startRow=1, startCol=1)位置提取3×3子数组,期望结果:
[8, 7, 6, 8, 3, 6, 8, 7, 6]
原有代码问题
原有实现仅适配9×9数组提取3×3子数组的特定场景,核心错误是误用子数组的总面积(kWH = subWidth * subHeight)计算索引偏移,完全不符合一维数组的行优先存储逻辑,无法适配通用情况(比如startRow=1, startCol=0时直接失效)。
原有代码:
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 }
通用解决方案
核心逻辑
要实现通用提取,必须明确原二维数组的列数(记为originalCols)——因为一维数组是按行优先拼接的,每一行的元素个数等于原数组的列数。
提取步骤:
- 计算子数组每一行在一维数组中的起始索引:
当前行偏移 = startRow + i(i从0到subHeight-1),对应一维索引为(startRow + i) * originalCols + startCol - 对每一行,从起始索引开始截取
subWidth个元素 - 将所有行的元素合并为一个一维数组
代码实现
const extractSubsetFrom1D = (array, originalCols, subHeight, subWidth, startRow, startCol) => { const result = []; // 遍历子数组的每一行 for (let i = 0; i < subHeight; i++) { // 计算当前行在一维数组中的起始索引 const rowStartIndex = (startRow + i) * originalCols + startCol; // 截取当前行的subWidth个元素,加入结果 result.push(...array.slice(rowStartIndex, rowStartIndex + subWidth)); } return result; }
测试示例
用开头的场景测试:
const array1D = [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]; // 原二维数组列数为5,提取3×3子数组,起始位置(1,1) const subset = extractSubsetFrom1D(array1D, 5, 3, 3, 1, 1); console.log(subset); // 输出: [8, 7, 6, 8, 3, 6, 8, 7, 6]
边界校验(可选)
如果需要避免非法输入(比如起始位置+子数组尺寸超出原数组范围),可以添加校验逻辑:
const extractSubsetFrom1D = (array, originalCols, subHeight, subWidth, startRow, startCol) => { // 计算原数组的行数 const originalRows = array.length / originalCols; // 校验输入合法性 if (!Number.isInteger(originalRows)) throw new Error('一维数组长度与原列数不匹配'); if (startRow + subHeight > originalRows) throw new Error('子数组高度超出原数组范围'); if (startCol + subWidth > originalCols) throw new Error('子数组宽度超出原数组范围'); const result = []; for (let i = 0; i < subHeight; i++) { const rowStartIndex = (startRow + i) * originalCols + startCol; result.push(...array.slice(rowStartIndex, rowStartIndex + subWidth)); } return result; }
内容的提问来源于stack exchange,提问作者amlwwalker
相关产品推荐
相关产品推荐

