假设我有一个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.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
会导致无限循环。
chunk
不为 0
,以避免无限循环。 - Steven Luconst array_chunks = (array, chunk_size) => Array(Math.ceil(array.length / chunk_size)).fill().map((_, index) => index * chunk_size).map(begin => array.slice(begin, begin + chunk_size));
可以将数组按指定大小切割成块。 - Константин Ван这里是一个使用reduce的ES6版本
const perChunk = 2 // items per chunk
const inputArray = ['a','b','c','d','e']
const result = inputArray.reduce((resultArray, item, index) => {
const chunkIndex = Math.floor(index/perChunk)
if(!resultArray[chunkIndex]) {
resultArray[chunkIndex] = [] // start a new chunk
}
resultArray[chunkIndex].push(item)
return resultArray
}, [])
console.log(result); // result: [['a','b'], ['c','d'], ['e']]
如果您准备进一步链接map/reduce操作,您可以放心,输入数组不会被修改。
如果您希望版本更加简短,但可读性较差,您可以在操作中添加一些concat
,以达到相同的结果:
inputArray.reduce((all,one,i) => {
const ch = Math.floor(i/perChunk);
all[ch] = [].concat((all[ch]||[]),one);
return all
}, [])
你可以使用取余运算符将连续的项放入不同的块中:
const ch = (i % perChunk);
5/2 = 2.5
,而 Math.floor(2.5) = 2
,因此索引为5的项将放置在桶2中。 - Andrei R改编自dbaseman的答案:https://dev59.com/OWPVa4cB1Zd3GeqP6Hsa#10456344
Object.defineProperty(Array.prototype, 'chunk_inefficient', {
value: function(chunkSize) {
var array = this;
return [].concat.apply([],
array.map(function(elem, i) {
return i % chunkSize ? [] : [array.slice(i, i + chunkSize)];
})
);
}
});
console.log(
[1, 2, 3, 4, 5, 6, 7].chunk_inefficient(3)
)
// [[1, 2, 3], [4, 5, 6], [7]]
小补充:
需要指出的是,上述方法在我看来并不够优雅,只是一个利用 Array.map
的简单解决方法。它实际上执行了以下操作,其中 ~ 表示连接:
[[1,2,3]]~[]~[]~[] ~ [[4,5,6]]~[]~[]~[] ~ [[7]]
这种方法与下面的方法具有相同的渐进运行时间,但由于生成空列表而可能导致更差的常量因子。 可以按照以下方式重写此方法(大部分与Blazemonger的方法相同,这就是我最初没有提交此答案的原因):
更有效的方法:
// refresh page if experimenting and you already defined Array.prototype.chunk
Object.defineProperty(Array.prototype, 'chunk', {
value: function(chunkSize) {
var R = [];
for (var i = 0; i < this.length; i += chunkSize)
R.push(this.slice(i, i + chunkSize));
return R;
}
});
console.log(
[1, 2, 3, 4, 5, 6, 7].chunk(3)
)
我现在更喜欢使用上述方法之一,或者以下的方法之一:
Array.range = function(n) {
// Array.range(5) --> [0,1,2,3,4]
return Array.apply(null,Array(n)).map((x,i) => i)
};
Object.defineProperty(Array.prototype, 'chunk', {
value: function(n) {
// ACTUAL CODE FOR CHUNKING ARRAY:
return Array.range(Math.ceil(this.length/n)).map((x,i) => this.slice(i*n,i*n+n));
}
});
演示:
> JSON.stringify( Array.range(10).chunk(3) );
[[1,2,3],[4,5,6],[7,8,9],[10]]
或者如果你不想使用Array.range函数,实际上只需要一行代码(不包括杂项):
var ceil = Math.ceil;
Object.defineProperty(Array.prototype, 'chunk', {value: function(n) {
return Array(ceil(this.length/n)).fill().map((_,i) => this.slice(i*n,i*n+n));
}});
Object.defineProperty(Array.prototype, 'chunk', {value: function(n) {
return Array.from(Array(ceil(this.length/n)), (_,i)=>this.slice(i*n,i*n+n));
}});
array.myCompanyFlatten
,那么没问题,但请不要添加array.flatten
,并祈祷它永远不会引起问题。正如您所看到的,mootools多年前的决定现在影响了TC39标准。 - Florian Wendelbornfunction* chunks(arr, n) {
for (let i = 0; i < arr.length; i += n) {
yield arr.slice(i, i + n);
}
}
let someArray = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
console.log([...chunks(someArray, 2)]) // [[0, 1], [2, 3], [4, 5], [6, 7], [8, 9]]
function* chunks<T>(arr: T[], n: number): Generator<T[], void> {
for (let i = 0; i < arr.length; i += n) {
yield arr.slice(i, i + n);
}
}
function* chunks<T>(arr: T[], n: number): Generator<T[], void> {
然后使用 const foo = [ ...chunks( bar, 4 ) ];
- @RayFoss - Stev如果你不知道谁会使用你的代码(第三方、同事、将来的自己等),请尽量避免对原型进行修改,包括 Array.prototype
。
虽然有安全地扩展原型的方法(但并非所有浏览器都支持),也有安全地使用从扩展原型创建的对象的方法,但更好的做法是遵循最小惊讶原则,完全避免这些做法。
如果你有时间,可以观看 Andrew Dupont 在 JSConf 2011 上的演讲"Everything is Permitted: Extending Built-ins",这个话题讨论得很好。
但回到问题上,尽管上述解决方案可行,但过于复杂,需要不必要的计算开销。以下是我的解决方案:
function chunk (arr, len) {
var chunks = [],
i = 0,
n = arr.length;
while (i < n) {
chunks.push(arr.slice(i, i += len));
}
return chunks;
}
// Optionally, you can do the following to avoid cluttering the global namespace:
Array.chunk = chunk;
使用 ES6 的 Splice 版本
let [list,chunkSize] = [[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15], 6];
list = [...Array(Math.ceil(list.length / chunkSize))].map(_ => list.splice(0,chunkSize))
console.log(list);
list
数组。 - Jacka.map((_,i) => list.slice(i*chuckSize,i*chuckSize+chuckSize))
的意思是将一个列表按照指定的块大小分割成多个子列表,可以很方便地实现。 - James Robeyvar split=(fields,record=2)=>
\n
fields.map((field,index,fields)=>
\n
fields.splice(index,record,fields.slice(index,record)));
- bpstrngr我在jsperf.com上测试了不同的答案。结果可在此处查看:https://web.archive.org/web/20150909134228/https://jsperf.com/chunk-mtds
而最快的函数(适用于IE8及以上版本)是这个:
function chunk(arr, chunkSize) {
if (chunkSize <= 0) throw "Invalid chunk size";
var R = [];
for (var i=0,len=arr.length; i<len; i+=chunkSize)
R.push(arr.slice(i,i+chunkSize));
return R;
}
function chunk(array: T[], chunkSize: number): T[][] {
const R: T[][] = [];
for (let i = 0, len = array.length; i < len; i += chunkSize)
R.push(array.slice(i, i + chunkSize));
return R;
}
该函数将一个传入的数组按照指定的大小分割成多个子数组,并返回一个包含这些子数组的二维数组。函数使用了 TypeScript 泛型,以便可接受任意类型的输入数组。 - MacKinley SmithchunkSize = 0
需要多长时间?一些有效的函数输入不应该停止进程。 - cevingArray<Array>
。而且非正的块大小没有任何意义。因此,对我来说抛出错误似乎是合理的。 - ceving我更倾向于使用splice方法:
var chunks = function(array, size) {
var results = [];
while (array.length) {
results.push(array.splice(0, size));
}
return results;
};
array = array.slice()
来创建一个浅拷贝。 - 3limin4t0r现在你可以使用lodash的chunk函数将数组分割成更小的数组https://lodash.com/docs#chunk,不再需要纠结于循环!
老问题:新答案!我实际上正在使用来自这个问题的一个答案,我的朋友对其进行了改进!所以这是它:
Array.prototype.chunk = function ( n ) {
if ( !this.length ) {
return [];
}
return [ this.slice( 0, n ) ].concat( this.slice(n).chunk(n) );
};
[1,2,3,4,5,6,7,8,9,0].chunk(3);
> [[1,2,3],[4,5,6],[7,8,9],[0]]
var chunk = (arr, n) => { if ( !arr.length ) return []; return [ arr.slice( 0, n ) ].concat( chunk(arr.slice(n), n) ) }
- Ed Williams