让我们说我有一个Javascript数组看起来如下:

["Element 1","Element 2","Element 3",...]; // with close to a hundred elements.

什么样的方法适合将数组分成许多更小的数组,假设最多有10个元素?


当前回答

array.slice()方法可以根据需要从数组的开头、中间或结尾提取切片,而不需要改变原始数组。

const chunkSize = 10;
for (let i = 0; i < array.length; i += chunkSize) {
    const chunk = array.slice(i, i + chunkSize);
    // do whatever
}

最后一个块可能小于chunkSize。例如,当给定一个包含12个元素的数组时,第一个块将有10个元素,第二个块只有2个。

注意,chunkSize为0将导致无限循环。

其他回答

对于功能性的解决方案,使用Ramda:

其中,popularProducts是输入数组,5是数据块大小

导入splitEvery from 'ramda/src/splitEvery' popularProducts splitEvery(5)。Map ((chunk, i) => { //用chunk做一些事情 })

下面是我使用Coffeescript列表理解的方法。可以在这里找到一篇详细介绍Coffeescript中的理解的好文章。

chunk: (arr, size) ->
    chunks = (arr.slice(index, index+size) for item, index in arr by size)
    return chunks

这是我能想到的最有效、最直接的解决方案:

function chunk(array, chunkSize) {
    let chunkCount = Math.ceil(array.length / chunkSize);
    let chunks = new Array(chunkCount);
    for(let i = 0, j = 0, k = chunkSize; i < chunkCount; ++i) {
        chunks[i] = array.slice(j, k);
        j = k;
        k += chunkSize;
    }
    return chunks;
}

尽量避免搞乱原生原型,包括Array。原型,如果你不知道谁将使用你的代码(第三方、同事、你自己等)。

有一些方法可以安全地扩展原型(但不是在所有浏览器中),也有一些方法可以安全地使用从扩展原型创建的对象,但更好的经验法则是遵循最小意外原则,并完全避免这些做法。

如果你有时间,可以看看Andrew Dupont的JSConf 2011演讲,“Everything is allowed: Extending Built-ins”,关于这个话题的讨论。

但回到问题上来,虽然上面的解决方案是可行的,但它们过于复杂,需要不必要的计算开销。以下是我的解决方案:

function chunk (arr, len) {

  var chunks = [],
      i = 0,
      n = arr.length;

  while (i < n) {
    chunks.push(arr.slice(i, i += len));
  }

  return chunks;
}

// Optionally, you can do the following to avoid cluttering the global namespace:
Array.chunk = chunk;

下面是一个使用ImmutableJS的解决方案,其中items是一个不可变列表,size是所需的分组大小。

const partition = ((items, size) => {
  return items.groupBy((items, i) => Math.floor(i/size))
})