Split array into chunks
The array.slice method can extract a slice from the beginning, middle, or end of an array for whatever purposes you require, without changing the original array.
var i,j, temporary, chunk = 10;for (i = 0,j = array.length; i < j; i += chunk) { temporary = array.slice(i, i + chunk); // do whatever}
Here's a ES6 version using reduce
var perChunk = 2 // items per chunk var inputArray = ['a','b','c','d','e']var 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']]
And you're ready to chain further map/reduce transformations.Your input array is left intact
If you prefer a shorter but less readable version, you can sprinkle some concat
into the mix for the same end result:
inputArray.reduce((all,one,i) => { const ch = Math.floor(i/perChunk); all[ch] = [].concat((all[ch]||[]),one); return all}, [])
Modified from an answer by dbaseman: https://stackoverflow.com/a/10456344/711085
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]]
minor addendum:
I should point out that the above is a not-that-elegant (in my mind) workaround to use Array.map
. It basically does the following, where ~ is concatenation:
[[1,2,3]]~[]~[]~[] ~ [[4,5,6]]~[]~[]~[] ~ [[7]]
It has the same asymptotic running time as the method below, but perhaps a worse constant factor due to building empty lists. One could rewrite this as follows (mostly the same as Blazemonger's method, which is why I did not originally submit this answer):
More efficient method:
// refresh page if experimenting and you already defined Array.prototype.chunkObject.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))
My preferred way nowadays is the above, or one of the following:
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)); }});
Demo:
> JSON.stringify( Array.range(10).chunk(3) );[[1,2,3],[4,5,6],[7,8,9],[10]]
Or if you don't want an Array.range function, it's actually just a one-liner (excluding the fluff):
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));}});
or
Object.defineProperty(Array.prototype, 'chunk', {value: function(n) { return Array.from(Array(ceil(this.length/n)), (_,i)=>this.slice(i*n,i*n+n));}});