【问题标题】:Chunk data from array of arrays来自数组数组的块数据
【发布时间】:2022-01-03 21:29:13
【问题描述】:

在将其标记为由另一个问题回答之前请注意这是一个数组数组,而不是一个平面数组,另外,我给出的数字是一个例子,我刚刚展示给你可以直观地看到正在发生的事情。

我正在尝试遍历数组数组。 我有以下数组:-

[
   [1, 2, 3, 4, 5, 6, 7, 8, 9],
   [1, 2, 3, 4, 5, 6, 7, 8, 9],
   [1, 2, 3, 4, 5, 6, 7, 8, 9],
   [3, 2, 1, 6, 5, 4, 9, 8, 7],
   [6, 5, 4, 9, 8, 7, 3, 2, 1],
   [7, 8, 9, 3, 2, 1, 6, 5, 4]
]

如何将此数组转换为 3x3 的块,例如:-

[
   [1, 2, 3, 1, 2, 3, 1, 2, 3],
   [4, 5, 6, 4, 5, 6, 4, 5, 6],
   [7, 8, 9, 7, 8, 9, 7, 8, 9],
   [3, 2, 1, 6, 5, 4, 9, 8, 7],
   [6, 5, 4, 9, 8, 7, 3, 2, 1],
   [7, 8, 9, 3, 2, 1, 6, 5, 4],
]

从上面的数组中可以看出,我使用每个数组的前 3 个值对它进行了分块,然后是每个数组的第二个 3n,最后是每个数组的最后一个 3n。

所以数组会像下面这样分块:-

1 2 3 | 4 5 6 | 7 8 9
1 2 3 | 4 5 6 | 7 8 9
1 2 3 | 4 5 6 | 7 8 9
---------------------
3 2 1 | 6 5 4 | 9 8 7
6 5 4 | 9 8 7 | 3 2 1
7 8 9 | 3 2 1 | 6 5 4

我尝试遍历每一行并在达到增量并增加行时重置列数,但这不起作用。

如果这有帮助,我可以用以前的尝试更新问题吗? 另外请注意,数组的大小不同,但总是可以被特定数字整除,对于上面的示例,我选择了数字 3。

我已用更多信息更新了问题。 数组的数组总是能被一个特定的数整除,这个例子显示了一个可整除的数 3。

【问题讨论】:

  • 请发表您解决问题的最佳尝试。
  • 一旦你对每个嵌套数组进行了分块,你应该能够遍历它们并连接每个数组的对应元素。
  • 外部数组的长度是否也能被块大小整除?
  • @pilchard 是的,很抱歉最初的混乱,我已经更新了这个问题。初始数组将始终可整除购买块大小。我的块大小是 20,但这里的块大小是 3,以便于示例。

标签: javascript arrays chunking


【解决方案1】:

这可以通过这个问题Split array into chunks 的块结合Javascript equivalent of Python's zip function 的 zip 来解决

这样做的好处是能够反转操作以恢复原始状态。

/** @see: https://stackoverflow.com/questions/8495687/split-array-into-chunks */
function chunk(array, chunk) {
    let result = [];
    for (let i = 0; i < array.length; i += chunk) {
        result.push(array.slice(i, i + chunk));
    }
    return result;
}

/** @see: https://stackoverflow.com/questions/4856717/javascript-equivalent-of-pythons-zip-function */
function zip(...rows) {
    return [...rows[0]].map((_, c) => rows.map((row) => row[c]));
}

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

const result = chunk(array, 3)
    .flatMap((innerChunk) =>
        zip(...innerChunk.map((arr) => chunk(arr, 3)))
        .map((arr) => arr.flat())
    );

console.log(result.map((a) => a.join(', ')));

// Allows the result to be reverted to the original
const reversed = chunk(result, 3)
    .flatMap((innerChunk) =>
        zip(...innerChunk.map((arr) => chunk(arr, 3)))
        .map((arr) => arr.flat())
    );

console.log(reversed.map((a) => a.join(', ')));

【讨论】:

  • 这个问题是如果数组有更多行,例如 6,它将获取所有前 3 个值并将它们推送到 result[0] 我会更新我的问题,对不起。
  • 已编辑。它仍然只是 chunk/zip,但您需要先对外部数组进行分块。
  • 太棒了,谢谢。我只是要在 JSFIddle 中弹出一个巨大的数组并更新块大小以查看它是否正常工作。
  • 我运行了一个包含 40k 数据点的样本,效果非常好。
  • 很高兴它有帮助。通读链接的问题,每个实用程序还有其他选项,包括使用生成器函数的实现,这可能在更大的输入上更有效。
【解决方案2】:

您可以使用嵌套循环来做到这一点,每次都根据外部数组的大小对数组进行切片。

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

let out = [];
for(let i in arr) { out.push([]);}

arr.forEach((e, i) => {
    let scale = e.length / arr.length;
    for(let j in arr)
    {
      out[j] = out[j].concat(e.slice(j * scale, j * scale + scale));
    }
});

console.log(out);

这里又是您编辑之前的原始数组:

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

let out = [];
for(let i in arr) { out.push([]);}

arr.forEach((e, i) => {
    let scale = e.length / arr.length;
    for(let j in arr)
    {
      out[j] = out[j].concat(e.slice(j * scale, j * scale + scale));
    }
});

console.log(out);

【讨论】:

  • 这个答案的唯一问题是数组是否有超过 3 行,例如,如果它有 6 个,则输出中的最后 3 个数组为空。 jsfiddle.net/zpLyg7xf
  • 我的原始答案假设您的数组的尺寸为[i][i^2]。我已经更新了我的答案,所以只要尺寸为[i][i*n],它现在就可以工作。如果内部数组长度不能被外部数组长度整除,则行为未定义。
  • 您的问题自您的原始帖子以来发生了如此巨大的变化,因此可能值得提出一个新问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-11-28
  • 2014-06-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多