让我们说我有一个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个元素?
当前回答
一个有效的解决方案是通过indexChunk将解决方案与slice和push连接起来,解决方案被分割成块:
function splitChunks(sourceArray, chunkSize) { if(chunkSize <= 0) throw "chunkSize must be greater than 0"; let result = []; for (var i = 0; i < sourceArray.length; i += chunkSize) { result[i / chunkSize] = sourceArray.slice(i, i + chunkSize); } return result; } let ar1 = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20 ]; console.log("Split in chunks with 4 size", splitChunks(ar1, 4)); console.log("Split in chunks with 7 size", splitChunks(ar1, 7));
其他回答
这是我使用的,它可能不是超级快,但它是紧凑和简单:
让chunksplit = (stream, size) => stream。Reduce ((chunk, item, idx, arr) => (idx % size == 0) ?[…块,加勒比海盗。Slice (idx, idx + size)]: chunk, []); //如果索引是chunksize的倍数,则添加新数组 让testArray =[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12日,13日,14日,15日,16日,17日,18日,19日,20日,21日,22日); document . write (JSON。stringify(chunksplit(testArray, 5)); / /使用JSON。要显示的嵌套数组的Stringify
当前排名靠前的答案存在的问题是,它们产生了不平衡的数据块。例如,当前接受的答案将把一个101个元素的数组分布为10个大小为10的块,后面是一个大小为1的块。
使用一些模块化算法可以创建统一的块大小,差异永远不会超过1:
函数split_array(a, nparts) { const quot = Math.floor;长度/ nparts) Const rem = a.length % nparts Var部件= [] For (var I = 0;I < nparts;+ + i) { const begin = i * quot +数学。分钟(rem,我) Const end = begin + quot + (i < rem) parts.push (a。片(开始、结束) } 返回部分 } Var chunk = split_array([1,2,3,4,5,6,7,8,9,10], 3) console.log (JSON.stringify(块)
输出:
[[1,2,3,4],[5,6,7],[8,9,10]]
(摘自相关答案)
使用Array.prototype.reduce()的另一个解决方案:
Const chunk = (array, size) => 数组中。Reduce ((acc, _, i) => { If (i % size === 0) ac .push(数组。切片(i, i + size)) 返回acc }, []) / /使用方法: Const数= [1,2,3,4,5,6,7,8,9,10] Const chunked = chunk(number, 3) console.log(分块)
这个解决方案与Steve Holgado的解决方案非常相似。但是,因为这个解决方案没有利用数组扩展,也没有在reducer函数中创建新数组,所以它比其他解决方案更快(参见jsPerf test),而且主观上更可读(语法更简单)。
在每n次迭代(其中n = size;从第一次迭代开始),累加器数组(acc)附加了数组的一个块(array。Slice (i, i + 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
}
迟到了,这是我的意见。就像很多人说的,我首先会想到的是
chunker = (a,n) => [...Array(Math.ceil(a.length/n))].map((v,i) => a.slice(i*n, (i+1)*n))
但我更喜欢但还没看到的是:
chunker = (n) => (r,v,i) => (c = Math.floor(i/n), (r[c] = r[c] || []).push(v), r)
console.log(arr.reduce(chunker(3), []))
有更长的变体
chunker = (a, n) => a.reduce((r,v,i) => {
c = Math.floor(i/n); // which chunk it belongs to
(r[c] = r[c] || []).push(v)
return r
}, [])
console.log(chunker(arr, 3))
解释
常见的答案将首先确定块的数量,然后根据块所在的位置和每个块的大小获得原始数组的切片 块减速器函数将遍历每个元素,并将其放入相应评估的块数组中。
性能几乎相同,据我所见,reduce方法平均慢了4%。
PS: reduce(ing)的优点是很容易改变分组标准。在问题和例子中,标准是相邻的单元格(映射使用切片)。但是你可能想要在“循环”中做它,例如,使用mod (% operator),或任何其他数学公式
重新阅读它让我发现这个公式也可以是一个参数,导致一个更通用的解决方案,需要2个函数来实现答案:
splitter = (a, f) => a.reduce((r,v,i) => { // math formula and/or function
c = f(v, i) || 0; // custom formula, receiving each value and index
(r[c] = r[c] || []).push(v)
return r
}, [])
chunker = (a, n) => splitter(a, (v,i) => Math.floor(i/n))
console.log(chunker(arr, 3))
console.log(splitter(arr, (v,i) => v % 2)) // is it even or odd?
splitter也可以用于创建命名数组,也就是对象,函数返回字符串而不是数字:)
我是这样解决的:
const chunks = [];
const chunkSize = 10;
for (let i = 0; i < arrayToSplit.length; i += chunkSize) {
const tempArray = arrayToSplit.slice(i, i + chunkSize);
chunks.push(tempArray);
}