让我们说我有一个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个元素?
当前回答
in coffeescript:
b = (a.splice(0, len) while a.length)
demo
a = [1, 2, 3, 4, 5, 6, 7]
b = (a.splice(0, 2) while a.length)
[ [ 1, 2 ],
[ 3, 4 ],
[ 5, 6 ],
[ 7 ] ]
其他回答
下面是使用reduce()方法的另一个解决方案,尽管与其他示例略有不同。希望我的解释也能更清楚一点。
Var arr = [0,1,2,3,4,5,6,7]; var chunkSize = 3; Arr = Arr。Reduce ((acc, item, idx) => { Let group = acc.pop(); 如果(集团。长度== chunkSize) { acc.push(集团); Group = []; } group.push(项); acc.push(集团); 返回acc; }, [[]]); console.log (arr);//打印[[0,1,2],[3,4,5],[6,7]]
解释
我们称之为reducer,它对数组中的每一项都使用pop()获取累加器的最后一项。记住,这个项是一个数组,它将最多为chunkSize数量的项进行分组(在本例中为3)。
当且仅当该组的数组长度等于chunksize时,我们需要将该组重新插入到累加器中并创建一个新组。
然后将当前项推入我们的组数组(它可能已经包含前面步骤中的0、1或2个项)。将当前项插入组后,我们需要将组重新插入到更大的集合中。
该过程将重复进行,直到遍历arr中的所有项。
注意,我们还使用[[]]为减速器提供了数组中空数组的起始值。
如果你正在使用下划线JS,只需使用:
var result = _.chunk(arr,elements_per_chunk)
无论如何,大多数项目已经使用下划线作为依赖项。
迟到了,这是我的意见。就像很多人说的,我首先会想到的是
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也可以用于创建命名数组,也就是对象,函数返回字符串而不是数字:)
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将导致无限循环。
这是一个带有尾递归和数组解构的版本。
远非最快的性能,但我只是觉得好笑,js现在可以做到这一点。即使它没有为此进行优化:(
const getChunks = (arr, chunk_size, acc = []) => {
if (arr.length === 0) { return acc }
const [hd, tl] = [ arr.slice(0, chunk_size), arr.slice(chunk_size) ]
return getChunks(tl, chunk_size, acc.concat([hd]))
}
// USAGE
const my_arr = [1,2,3,4,5,6,7,8,9]
const chunks = getChunks(my_arr, 2)
console.log(chunks) // [[1,2],[3,4], [5,6], [7,8], [9]]