让我们说我有一个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个元素?
当前回答
如果你使用EcmaScript >= 5.1版本,你可以使用array.reduce()实现一个函数版本的chunk(),复杂度为O(N):
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的解释:
如果之前的值,即之前返回的块数组是空的,或者如果之前的最后一个块有chunkSize项,则创建一个新的块 将新数据块添加到现有数据块数组中 否则,当前块是块数组中的最后一个块 将当前值添加到块中 返回修改后的块数组 通过传递一个空数组初始化还原
基于chunkSize的curry:
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' ] ]
其他回答
超级晚,但我解决了一个类似的问题,使用.join("")的方法将数组转换为一个巨大的字符串,然后使用regex将.match(/.{1,7}/)它转换为最大长度为7的子字符串数组。
const arr = ['abc', 'def', 'gh', 'ijkl', 'm', 'nopq', 'rs', 'tuvwx', 'yz'];
const arrayOfSevens = arr.join("").match(/.{1,7}/g);
// ["abcdefg", "hijklmn", "opqrstu", "vwxyz"]
看看这个在速度测试中如何与其他方法进行比较会很有趣吗
下面是一个使用ImmutableJS的解决方案,其中items是一个不可变列表,size是所需的分组大小。
const partition = ((items, size) => {
return items.groupBy((items, i) => Math.floor(i/size))
})
为这个https://www.npmjs.com/package/array.chunk创建一个npm包
var result = [];
for (var i = 0; i < arr.length; i += size) {
result.push(arr.slice(i, size + i));
}
return result;
当使用TypedArray时
var result = [];
for (var i = 0; i < arr.length; i += size) {
result.push(arr.subarray(i, size + i));
}
return result;
好吧,让我们从一个相当严格的开始:
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);
然后我们就有了这个紧密的减速器函数:
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),[]);
因为当我们将它绑定到一个数字时,小猫就死了,我们可以像这样手动curry:
// 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);
我更喜欢使用拼接法而不是切片法。 这个解决方案使用数组长度和块大小来创建循环计数,然后循环遍历数组,在每个步骤中由于拼接而在每个操作后变得更小。
function chunk(array, size) {
let resultArray = [];
let chunkSize = array.length/size;
for(i=0; i<chunkSize; i++) {
resultArray.push(array.splice(0, size));
}
return console.log(resultArray);
}
chunk([1,2,3,4,5,6,7,8], 2);
如果不想改变原始数组,可以使用展开操作符克隆原始数组,然后使用该数组来解决问题。
let clonedArray = [...OriginalArray]