将数组分成块

1005

假设我有一个JavaScript数组,如下所示:

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

如何将一个数组分成多个小数组,每个小数组最多包含10个元素?


参见 如何将长数组拆分为较小的数组使用underscore.js拆分javascript数组 (以及链接问题中的许多重复项 linked questions)。 - Bergi
可能是将JS数组分成N个数组的重复问题。 - T J
70
对于lodash用户,您需要查找_.chunk - Ulysse BN
如果你需要最后一个块的最小大小,这里有几个选项:https://stackoverflow.com/questions/57908133/splitting-an-array-up-into-chunks-of-a-given-size-with-a-minimum-chunk-size - Ahmet Cetin
我创建了一个解决方案,合并了最佳答案:https://dev59.com/4Goy5IYBdhLWcg3wg-Ym#71483760 - Fernando Leal
@webatrisans 这回答了你的问题。如果你使用正确的标签,那么我们更容易给出正确的指针指向正确的重复内容。 - RiggsFolly
84个回答

9

const array = ['a', 'b', 'c', 'd', 'e'];
const size = 2;
const chunks = [];
while (array.length) {
    chunks.push(array.splice(0, size));
}
console.log(chunks);


9
如果您使用的是 EcmaScript 版本 >= 5.1,您可以使用 array.reduce() 实现一个具有 O(N) 复杂度的函数版本的 chunk()

function chunk(chunkSize, array) {
    return array.reduce(function(previous, current) {
        var chunk;
        if (previous.length === 0 || 
                previous[previous.length -1].length === chunkSize) {
            chunk = [];   // 1
            previous.push(chunk);   // 2
        }
        else {
            chunk = previous[previous.length -1];   // 3
        }
        chunk.push(current);   // 4
        return previous;   // 5
    }, []);   // 6
}

console.log(chunk(2, ['a', 'b', 'c', 'd', 'e']));
// prints [ [ 'a', 'b' ], [ 'c', 'd' ], [ 'e' ] ]

上面每个// nbr的解释如下:

  1. 如果先前的值,即先前返回的块数组为空或最后一个先前的块具有chunkSize项,则创建一个新块
  2. 将新块添加到现有块数组中
  3. 否则,当前块是块数组中的最后一个块
  4. 将当前值添加到块中
  5. 返回修改后的块数组
  6. 通过传递空数组来初始化缩减

基于 chunkSize 的柯里化:
var chunk3 = function(array) {
    return chunk(3, array);
};

console.log(chunk3(['a', 'b', 'c', 'd', 'e']));
// prints [ [ 'a', 'b', 'c' ], [ 'd', 'e' ] ]

你可以将chunk()函数添加到全局Array对象中:

Object.defineProperty(Array.prototype, 'chunk', {
    value: function(chunkSize) {
        return this.reduce(function(previous, current) {
            var chunk;
            if (previous.length === 0 || 
                    previous[previous.length -1].length === chunkSize) {
                chunk = [];
                previous.push(chunk);
            }
            else {
                chunk = previous[previous.length -1];
            }
            chunk.push(current);
            return previous;
        }, []);
    }
});

console.log(['a', 'b', 'c', 'd', 'e'].chunk(4));
// prints [ [ 'a', 'b', 'c' 'd' ], [ 'e' ] ]


9
使用 lodash 中的 chunk。
lodash.chunk(arr,<size>).forEach(chunk=>{
  console.log(chunk);
})

9

js

function splitToBulks(arr, bulkSize = 20) {
    const bulks = [];
    for (let i = 0; i < Math.ceil(arr.length / bulkSize); i++) {
        bulks.push(arr.slice(i * bulkSize, (i + 1) * bulkSize));
    }
    return bulks;
}

console.log(splitToBulks([1, 2, 3, 4, 5, 6, 7], 3));

typescript

function splitToBulks<T>(arr: T[], bulkSize: number = 20): T[][] {
    const bulks: T[][] = [];
    for (let i = 0; i < Math.ceil(arr.length / bulkSize); i++) {
        bulks.push(arr.slice(i * bulkSize, (i + 1) * bulkSize));
    }
    return bulks;
}

8

Here is an example where I split an array into chunks of 2 elements, simply by splicing chunks out of the array until the original array is empty.

    const array = [86,133,87,133,88,133,89,133,90,133];
    const new_array = [];

    const chunksize = 2;
    while (array.length) {
        const chunk = array.splice(0,chunksize);
        new_array.push(chunk);
    }

    console.log(new_array)


1
虽然这可能回答了问题,但稍微解释一下会非常有帮助,请点击编辑并输入一些解释。 - U13-Forward

8

您可以使用这个易于使用的 ES6 chunk 函数:

const chunk = (array, size) =>
  Array.from({length: Math.ceil(array.length / size)}, (value, index) => array.slice(index * size, index * size + size));

const itemsPerChunk = 3;
const inputArray = ['a', 'b', 'c', 'd', 'e', 'f', 'g'];

const newArray = chunk(inputArray, itemsPerChunk);
console.log(newArray.length); // 3,

document.write(JSON.stringify(newArray)); //  [ [ 'a', 'b', 'c' ], [ 'd', 'e', 'f' ], [ 'g' ] ]


喜欢这个一行代码,主要是因为它不会创建任何中间辅助数组,而是一些相当小的对象。 - Thomas Urban

8

您可以使用 Array.prototype.reduce 函数在一行代码中完成此操作。

let arr = [1,2,3,4];
function chunk(arr, size)
{
    let result = arr.reduce((rows, key, index) => (index % size == 0 ? rows.push([key]) : rows[rows.length-1].push(key)) && rows, []);
    return result;
}
        
console.log(chunk(arr,2));


8

纯JavaScript的一行代码:

function chunks(array, size) {
  return Array.apply(0,{length: Math.ceil(array.length / size)}).map((_, index) => array.slice(index*size, (index+1)*size))
}

// The following will group letters of the alphabet by 4
console.log(chunks([...Array(26)].map((x,i)=>String.fromCharCode(i + 97)), 4))


8
results = []
chunk_size = 10
while(array.length > 0){
   results.push(array.splice(0, chunk_size))
}

1
不确定为什么这个被踩了,但是代码需要一些解释。 - jpaugh
4
因为切割会破坏原始数组。 - metalim

7

这是我对此话题的贡献。我想.reduce()是最好的方式。

var segment = (arr, n) => arr.reduce((r,e,i) => i%n ? (r[r.length-1].push(e), r)
                                                    : (r.push([e]), r), []),
        arr = Array.from({length: 31}).map((_,i) => i+1);
        res = segment(arr,7);
console.log(JSON.stringify(res));

但是上述实现并不是很高效,因为.reduce()会遍历整个arr函数。一个更有效的方法(非常接近最快的命令式解决方案)是,迭代缩小(以进行分块)的数组,因为我们可以通过Math.ceil(arr/n);预先计算它的大小。一旦我们得到了空的结果数组,比如Array(Math.ceil(arr.length/n)).fill();,其余的就是将arr数组的片段映射到其中。

function chunk(arr,n){
  var r = Array(Math.ceil(arr.length/n)).fill();
  return r.map((e,i) => arr.slice(i*n, i*n+n));
}

arr = Array.from({length: 31},(_,i) => i+1);
res = chunk(arr,7);
console.log(JSON.stringify(res));

到目前为止,一切都很好,但我们仍然可以进一步简化上述片段。

var chunk = (a,n) => Array.from({length: Math.ceil(a.length/n)}, (_,i) => a.slice(i*n, i*n+n)),
    arr   = Array.from({length: 31},(_,i) => i+1),
    res   = chunk(arr,7);

console.log(JSON.stringify(res));


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接