114

How to split an array (which has 10 items) into 4 chunks, which contain a maximum of n items.

var a = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'];
//a function splits it to four arrays.
console.log(b, c, d, e);

And it prints:

['a', 'b', 'c']
['d', 'e', 'f']
['j', 'h', 'i']
['j']

The above assumes n = 3, however, the value should be dynamic.

Thanks

Robert
  • 8,717
  • 2
  • 27
  • 34
mrdaliri
  • 7,148
  • 22
  • 73
  • 107

2 Answers2

220

It could be something like that:

var a = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'];

var arrays = [], size = 3;
    
while (a.length > 0)
  arrays.push(a.splice(0, size));

console.log(arrays);

See splice Array's method.

An alternative method that does not mutate the array, beside create a shallow copy of it before chunk it, could be done by using slice and a for…loop:

var a = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'];

var arrays = [], size = 3;
    
for (let i = 0; i < a.length; i += size)
   arrays.push(a.slice(i, i + size));

console.log(arrays);

While a more functional programming oriented approach, could be:

const chunks = (a, size) =>
    Array.from(
        new Array(Math.ceil(a.length / size)),
        (_, i) => a.slice(i * size, i * size + size)
    );

let a = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'];

console.log(chunks(a, 3));
console.log(chunks(a, 2));

See Array.from and how new Array(n) works, specifically.

ZER0
  • 24,846
  • 5
  • 51
  • 54
75

Maybe this code helps:

var chunk_size = 10;
var arr = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17];
var groups = arr.map( function(e,i){ 
     return i%chunk_size===0 ? arr.slice(i,i+chunk_size) : null; 
}).filter(function(e){ return e; });
console.log({arr, groups})
ibenjelloun
  • 7,425
  • 2
  • 29
  • 53
Mirodil
  • 2,321
  • 2
  • 30
  • 38
  • 7
    I like your solution. I cleaned it up a bit and made it a JS Bin. Thanks! http://jsbin.com/dokivomuzake/1/edit?js,console – dbasch Aug 24 '14 at 16:53
  • Much better functional solution. – Régis Oct 05 '16 at 04:28
  • 6
    `const partitionArray = (array, size) => array.map( (e,i) => (i % size === 0) ? array.slice(i, i + size) : null ) .filter( (e) => e )` – ztrange Mar 01 '17 at 21:32
  • Perfect solution. +10 – George Chalhoub Mar 27 '17 at 15:07
  • 2
    Within the `map` you can simplify it by using `return i%chunk_size===0 && arr.slice(i,i+chunk_size);` – Koen. Apr 10 '17 at 19:22
  • how to split it into two chunks but include the value from the previous chunk? – Syed Ariff Oct 02 '18 at 06:24
  • 2
    @Buts - [`map`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map) iterates through each element of the array. – David Nov 18 '18 at 22:58
  • This goes through a lot of iterations that aren't necessary. With the values given it does 17 iterations (34 if you consider `filter`) of which only 2 are used. – Sandy Gifford Mar 04 '19 at 20:07
  • @SandyGifford for liner version you can try this one `arr.reduce((r,e,i) => { i%chunk_size===0 ? r.push([e]) : r[r.length-1].push(e); return r; },[])` – Mirodil Mar 05 '19 at 16:00
  • @Mirodil That's slightly better, but you're almost certainly going to get better performance out of letting slice do the second level of iteration for you: https://stackoverflow.com/a/7273717/1496453 - more readable, too. – Sandy Gifford Mar 05 '19 at 17:36
  • @SandyGifford it is the same as https://stackoverflow.com/questions/11318680/split-array-into-chunks-of-n-length#11318797 solution, and it gives bit more performance if you change `splice` – Mirodil Mar 05 '19 at 21:16
  • `array.map((item, index) => index % chunk_size === 0 ? array.slice(index, index + chunk_size) : null).filter(Boolean)` is more modern and cleaner – cesargdm Sep 14 '21 at 20:17