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

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

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


当前回答

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

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;
}

其他回答

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

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

下面的ES2015方法不需要定义函数,直接在匿名数组上工作(例如块大小为2):

[11,22,33,44,55].map((_, i, all) => all.slice(2*i, 2*i+2)).filter(x=>x.length)

如果你想为此定义一个函数,你可以这样做(改进K._对Blazemonger的回答的评论):

const array_chunks = (array, chunk_size) => array
    .map((_, i, all) => all.slice(i*chunk_size, (i+1)*chunk_size))
    .filter(x => x.length)

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

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

修改自dbaseman的回答:https://stackoverflow.com/a/10456344/711085

Object.defineProperty(Array.prototype, ' chunk_efficient ', { 值:function(chunkSize) { Var数组= this; 返回[].concat.apply ([], 数组中。映射(函数(elem, i) { 返回i % chunkSize ?[]: [array.]slice(i, i + chunkSize)]; }) ); } }); console.log ( [1,2,3,4,5,6,7]. chunk_efficient (3) ) // [[1,2,3], [4,5,6], [7]]


小齿顶:

我应该指出,上面的方法(在我看来)并不是使用Array.map的一种优雅的变通方法。它基本上做以下事情,其中~是连接:

[[1,2,3]]~[]~[]~[] ~ [[4,5,6]]~[]~[]~[] ~ [[7]]

它与下面的方法具有相同的渐近运行时间,但由于构建空列表,可能是一个更糟糕的常数因子。可以重写如下(与Blazemonger的方法大致相同,这就是我最初没有提交这个答案的原因):

更有效的方法:

如果你已经定义了Array.prototype.chunk,则刷新页面 Object.defineProperty(Array.prototype, 'chunk', { 值:function(chunkSize) { var R = []; For (var I = 0;I < this.length;i += chunkSize) R.push(这一点。slice(i, i + chunkSize)); 返回R; } }); console.log ( [1, 2, 3, 4, 5, 6, 7].chunk(3) )


我现在喜欢的方式是上面的,或者是下面的一种:

Array.range = function(n) {
  // Array.range(5) --> [0,1,2,3,4]
  return Array.apply(null,Array(n)).map((x,i) => i)
};

Object.defineProperty(Array.prototype, 'chunk', {
  value: function(n) {

    // ACTUAL CODE FOR CHUNKING ARRAY:
    return Array.range(Math.ceil(this.length/n)).map((x,i) => this.slice(i*n,i*n+n));

  }
});

演示:

> JSON.stringify( Array.range(10).chunk(3) );
[[1,2,3],[4,5,6],[7,8,9],[10]]

或者如果你不想要数组。Range函数,它实际上只是一行代码(不包括有绒毛的部分):

var ceil = Math.ceil;

Object.defineProperty(Array.prototype, 'chunk', {value: function(n) {
    return Array(ceil(this.length/n)).fill().map((_,i) => this.slice(i*n,i*n+n));
}});

or

Object.defineProperty(Array.prototype, 'chunk', {value: function(n) {
    return Array.from(Array(ceil(this.length/n)), (_,i)=>this.slice(i*n,i*n+n));
}});

使用发电机

函数*块(arr, n) { 对于(设I = 0;I < arrr .length;I += n) { 加勒比海盗。Slice (i, i + n); } } let someArray = [0,1,2,3,4,5,6,7,8,9] console.log([…块(someArray, 2)]) / /[[0, 1],[2、3],[4,5],[6、7],[8 9]]

可以像这样用Typescript输入:

function* chunks<T>(arr: T[], n: number): Generator<T[], void> {
  for (let i = 0; i < arr.length; i += n) {
    yield arr.slice(i, i + n);
  }
}