Skip to content

将JavaScript数组分成块

将数组分成指定大小的块

要将数组分成指定大小的块,您需要知道将产生的块的数量。可以通过将数组的长度除以每个块的大小并四舍五入到最近的整数来计算。可以使用Math.ceil()函数来实现。

使用该数字,您可以使用Array.from()函数创建一个指定长度的新数组。Array.from()的第二个参数是一个映射函数,它将为新数组的每个元素调用。结合Array.prototype.slice()函数,您可以将新数组的每个元素映射到一个长度为size的块。如果原始数组无法均匀分割,最后一个块将包含剩余的元素。

const chunk = (arr, size) =>
  Array.from({ length: Math.ceil(arr.length / size) }, (v, i) =>
    arr.slice(i * size, i * size + size)
  );

chunk([1, 2, 3, 4, 5], 2); // [[1, 2], [3, 4], [5]]

将数组分成给定数量的块

类似地,要将数组分成给定数量的块,您需要知道每个块的大小。可以通过将数组的长度除以块的数量并四舍五入到最近的整数来计算。其余的过程与上述相同。

const chunkIntoN = (arr, n) => {
  const size = Math.ceil(arr.length / n);
  return Array.from({ length: n }, (v, i) =>
    arr.slice(i * size, i * size + size)
  );
}

chunkIntoN([1, 2, 3, 4, 5, 6, 7], 4); // [[1, 2], [3, 4], [5, 6], [7]]

将数组分成块,不留下单独的元素

如前所述,最后一块可能包含的元素数量少于指定的大小,如果原始数组无法均匀分割。为了改变这种行为,您可以修改代码片段以适应一个额外的参数来表示最小块大小

我们首先使用取模运算符(%来计算将数组分成指定大小的块后剩余的元素数量。根据余数是否小于最小块大小,我们可以使用Math.floor()Math.ceil()来计算块的数量。

其余的过程基本相同。唯一值得注意的例外是最后一块的计算稍有不同,因为如果余数小于最小块大小,它需要包含剩余的元素。

const chunkWithMinSize = (arr, chunkSize, minChunkSize = 0) => {
  const remainder = arr.length % chunkSize;
  const isLastChunkTooSmall = remainder < minChunkSize;
  const totalChunks = isLastChunkTooSmall
    ? Math.floor(arr.length / chunkSize)
    : Math.ceil(arr.length / chunkSize);
  return Array.from({ length: totalChunks }, (_, i) => {
    const chunk = arr.slice(i * chunkSize, i * chunkSize + chunkSize);
    if (i === totalChunks - 1 && isLastChunkTooSmall)
      chunk.push(...arr.slice(-remainder));
    return chunk;
  });
};

const x = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11];

chunkWithMinSize(x, 5, 3); // [[1, 2, 3, 4, 5], [6, 7, 8, 9, 10, 11]]
chunkWithMinSize(x, 4, 2); // [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11]]

将可迭代对象分成给定大小的块

任何可迭代对象都可以使用类似的方式进行分块,使用生成器函数。唯一的区别是需要使用for...of循环迭代可迭代对象,而不是使用Array.prototype.slice()。这是因为无法提前确定块的数量

每次迭代的值都会添加到当前的chunk中,使用Array.prototype.push()。一旦chunk达到指定的size,您可以yield该值并将chunk重置为空数组。最后,您可以检查最后的chunk是否非空,并将其yield出来。

const chunkify = function* (itr, size) {
  let chunk = [];
  for (const v of itr) {
    chunk.push(v);
    if (chunk.length === size) {
      yield chunk;
      chunk = [];
    }
  }
  if (chunk.length) yield chunk;
};

const x = new Set([1, 2, 1, 3, 4, 1, 2, 5]);

[...chunkify(x, 2)]; // [[1, 2], [3, 4], [5]]
const chunkify = function* (itr, size) {
  let chunk = [];
  for (const v of itr) {
    chunk.push(v);
    if (chunk.length === size) {
      yield chunk;
      chunk = [];
    }
  }
  if (chunk.length) yield chunk;
};

const x = new Set([1, 2, 1, 3, 4, 1, 2, 5]);

[...chunkify(x, 2)]; // [[1, 2], [3, 4], [5]]