假设我有一个JavaScript数组,如下所示:
["Element 1","Element 2","Element 3",...]; // with close to a hundred elements.
如何将一个数组分成多个小数组,每个小数组最多包含10个元素?
假设我有一个JavaScript数组,如下所示:
["Element 1","Element 2","Element 3",...]; // with close to a hundred elements.
如何将一个数组分成多个小数组,每个小数组最多包含10个元素?
使用Array.prototype.reduce()
的另一种解决方案:
const chunk = (array, size) =>
array.reduce((acc, _, i) => {
if (i % size === 0) acc.push(array.slice(i, i + size))
return acc
}, [])
// Usage:
const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
const chunked = chunk(numbers, 3)
console.log(chunked)
这个解决方案与 Steve Holgado的解决方案非常相似。 但是,因为这个解决方案不利用数组扩展并且不在还原函数中创建新数组,所以它比其他解决方案更快(请参见 jsPerf测试)并且在主观上更易读(语法更简单)。
在每个第n个迭代(其中n= size
;从第一个迭代开始),累加器数组(acc
)附加了一块数组(array.slice(i, i+ size)
),然后返回。 在其他迭代中,将累加器数组返回为原样。
如果size
为零,则该方法返回空数组。 如果size
为负数,则该方法返回错误结果。 因此,如果您的情况需要,在负面或非正size
值方面,您可能需要采取一些措施。
如果速度在您的情况下很重要,则使用简单的for
循环比使用reduce()
更快(请参见 jsPerf测试),某些人也可能认为这种风格更易读:
function chunk(array, size) {
// This prevents infinite loops
if (size < 1) throw new Error('Size must be positive')
const result = []
for (let i = 0; i < array.length; i += size) {
result.push(array.slice(i, i + size))
}
return result
}
已经有很多答案了,但这是我使用的:
const chunk = (arr, size) =>
arr
.reduce((acc, _, i) =>
(i % size)
? acc
: [...acc, arr.slice(i, i + size)]
, [])
// USAGE
const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
chunk(numbers, 3)
// [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10]]
首先,当将索引除以块大小时,请检查是否有余数。
如果有余数,则只需返回累加器数组。
如果没有余数,则索引可被块大小整除,因此从原始数组中取出一个切片(从当前索引开始),并将其添加到累加器数组中。
因此,每次 reduce 迭代的返回的累加器数组看起来像这样:
// 0: [[1, 2, 3]]
// 1: [[1, 2, 3]]
// 2: [[1, 2, 3]]
// 3: [[1, 2, 3], [4, 5, 6]]
// 4: [[1, 2, 3], [4, 5, 6]]
// 5: [[1, 2, 3], [4, 5, 6]]
// 6: [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
// 7: [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
// 8: [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
// 9: [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10]]
我认为这是一个很好的使用ES6语法的递归解决方案:
const chunk = function(array, size) {
if (!array.length) {
return [];
}
const head = array.slice(0, size);
const tail = array.slice(size);
return [head, ...chunk(tail, size)];
};
console.log(chunk([1,2,3], 2));
const chunk = (a,n)=>[...Array(Math.ceil(a.length/n))].map((_,i)=>a.slice(n*i,n+n*i));
const chunk = <T>(arr: T[], size: number): T[][] =>
[...Array(Math.ceil(arr.length / size))].map((_, i) =>
arr.slice(size * i, size + size * i)
);
const chunk = (a,n)=>[...Array(Math.ceil(a.length/n))].map((_,i)=>a.slice(n*i,n+n*i));
document.write(JSON.stringify(chunk([1, 2, 3, 4], 2)));
const part=(a,n)=>[...Array(n)].map((_,i)=>a.slice(i*Math.ceil(a.length/n),(i+1)*Math.ceil(a.length/n)));
const part = <T>(a: T[], n: number): T[][] => {
const b = Math.ceil(a.length / n);
return [...Array(n)].map((_, i) => a.slice(i * b, (i + 1) * b));
};
const part = (a, n) => {
const b = Math.ceil(a.length / n);
return [...Array(n)].map((_, i) => a.slice(i * b, (i + 1) * b));
};
document.write(JSON.stringify(part([1, 2, 3, 4, 5, 6], 2))+'<br/>');
document.write(JSON.stringify(part([1, 2, 3, 4, 5, 6, 7], 2)));
chunk([1,2,3,4],2)
的结果是 [ [ 1, 2 ], [ 3, 4 ], [] ]
。这个结果对我来说似乎不正确。 - Hans BouwmeesterArray(n)
,第二个是由 [... ]
包装第一个数组产生的。由 map()
创建出来的结果数组并不是这两个数组之一。你可以使用 Array(n).fill(0)
来替换 [...Array(n)]
以消除一个数组。 - Thomas Urban好的,让我们从一道比较难的题目开始:
function chunk(arr, n) {
return arr.slice(0,(arr.length+n-1)/n|0).
map(function(c,i) { return arr.slice(n*i,n*i+n); });
}
这是这样使用的:
chunk([1,2,3,4,5,6,7], 2);
那么我们有这个紧缩的 reducer 函数:
function chunker(p, c, i) {
(p[i/this|0] = p[i/this|0] || []).push(c);
return p;
}
这是用法:
[1,2,3,4,5,6,7].reduce(chunker.bind(3),[]);
由于将 this
绑定到数字上会导致函数无法正常工作,因此我们可以使用手动柯里化来替代这种方式:
// Fluent alternative API without prototype hacks.
function chunker(n) {
return function(p, c, i) {
(p[i/n|0] = p[i/n|0] || []).push(c);
return p;
};
}
这个用法如下:
[1,2,3,4,5,6,7].reduce(chunker(3),[]);
然后是一个非常紧凑的函数,可以一次性完成所有操作:
function chunk(arr, n) {
return arr.reduce(function(p, cur, i) {
(p[i/n|0] = p[i/n|0] || []).push(cur);
return p;
},[]);
}
chunk([1,2,3,4,5,6,7], 3);
(p[i/n|0] || (p[i/n|0] = []))
这个表达式,这样如果不必要的话就不需要进行赋值操作。 - yckartthisArg
= null
,例如 chunker.bind(null, 3)
。文档 Function.prototype.bind() - Michal Miky Jankovský我旨在创建一个纯ES6的简单非变异解决方案。JavaScript中的特殊性使得在映射之前填充空数组成为必要 :-(
function chunk(a, l) {
return new Array(Math.ceil(a.length / l)).fill(0)
.map((_, n) => a.slice(n*l, n*l + l));
}
这个递归版本看起来更简单、更有说服力:function chunk(a, l) {
if (a.length == 0) return [];
else return [a.slice(0, l)].concat(chunk(a.slice(l), l));
}
ES6中极其脆弱的数组函数经常用于制作有趣的谜题 :-)
fill
中删除 0
,它仍然可以工作,这样 fill
看起来更合理,个人认为。 - Coert Grobbelaar为此创建了一个npm包,https://www.npmjs.com/package/array.chunk
var result = [];
for (var i = 0; i < arr.length; i += size) {
result.push(arr.slice(i, size + i));
}
return result;
var result = [];
for (var i = 0; i < arr.length; i += size) {
result.push(arr.subarray(i, size + i));
}
return result;
TypedArray
没有 slice
方法,我们可以使用 subarray
代替 https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/subarray - zhiyeleeArray.prototype.splice()
方法,不断地对数组进行切片,直到数组中没有元素。
Array.prototype.chunk = function(size) {
let result = [];
while(this.length) {
result.push(this.splice(0, size));
}
return result;
}
const arr = [1, 2, 3, 4, 5, 6, 7, 8, 9];
console.log(arr.chunk(2));
Array.prototype.splice()
方法会修改原始数组, 在执行 chunk()
后,原始数组 (arr
) 会变成 []
。
如果你想保持原始数组不变,那么请复制并保存 arr
的数据到另一个数组,并执行相同的操作。
Array.prototype.chunk = function(size) {
let data = [...this];
let result = [];
while(data.length) {
result.push(data.splice(0, size));
}
return result;
}
const arr = [1, 2, 3, 4, 5, 6, 7, 8, 9];
console.log('chunked:', arr.chunk(2));
console.log('original', arr);
附言:感谢 @mts-knn 提到这件事情。
console.log(arr);
,它将记录 []
,即 arr
将成为空数组。 - Matias Kinnunen[11,22,33,44,55].map((_, i, all) => all.slice(2*i, 2*i+2)).filter(x=>x.length)
const array_chunks = (array, chunk_size) => array
.map((_, i, all) => all.slice(i*chunk_size, (i+1)*chunk_size))
.filter(x => x.length)
我推荐使用lodash。在那里,分块是其中许多有用的功能之一。 说明:
npm i --save lodash
包含在您的项目中:
import * as _ from 'lodash';
使用方法:
const arrayOfElements = ["Element 1","Element 2","Element 3", "Element 4", "Element 5","Element 6","Element 7","Element 8","Element 9","Element 10","Element 11","Element 12"]
const chunkedElements = _.chunk(arrayOfElements, 10)
您可以在这里找到我的示例: https://playcode.io/659171/