[javascript] Split array into chunks

Let's say that I have an Javascript array looking as following:

["Element 1","Element 2","Element 3",...]; // with close to a hundred elements.

What approach would be appropriate to chunk (split) the array into many smaller arrays with, lets say, 10 elements at its most?

This question is related to javascript arrays split

The answer is


Well, a nice function for this would be:

function chunk(arr,times){
    if(times===null){var times = 10} //Fallback for users wanting to use the default of ten
   var tempArray = Array() //Array to be populated with chunks
    for(i=0;i<arr.length/times;i++){
     tempArray[i] = Array() //Sub-Arrays        //Repeats for each chunk         
   for(j=0;j<times;j++){
        if(!(arr[i*times+j]===undefined)){tempArray[i][j] = arr[i*times+j]//Populate Sub-  Arrays with chunks
    }
     else{
       j = times //Stop loop
       i = arr.length/times //Stop loop
  }
    }
     }
   return tempArray //Return the populated and chunked array
   }

Usage would be:

chunk(array,sizeOfChunks)

I commented it so you could understand what was going on.

(The formatting is a bit off, I programmed this on mobile)


If you use EcmaScript version >= 5.1, you can implement a functional version of chunk() using array.reduce() that has O(N) complexity:

_x000D_
_x000D_
function chunk(chunkSize, array) {_x000D_
    return array.reduce(function(previous, current) {_x000D_
        var chunk;_x000D_
        if (previous.length === 0 || _x000D_
                previous[previous.length -1].length === chunkSize) {_x000D_
            chunk = [];   // 1_x000D_
            previous.push(chunk);   // 2_x000D_
        }_x000D_
        else {_x000D_
            chunk = previous[previous.length -1];   // 3_x000D_
        }_x000D_
        chunk.push(current);   // 4_x000D_
        return previous;   // 5_x000D_
    }, []);   // 6_x000D_
}_x000D_
_x000D_
console.log(chunk(2, ['a', 'b', 'c', 'd', 'e']));_x000D_
// prints [ [ 'a', 'b' ], [ 'c', 'd' ], [ 'e' ] ]
_x000D_
_x000D_
_x000D_

Explanation of each // nbr above:

  1. Create a new chunk if the previous value, i.e. the previously returned array of chunks, is empty or if the last previous chunk has chunkSize items
  2. Add the new chunk to the array of existing chunks
  3. Otherwise, the current chunk is the last chunk in the array of chunks
  4. Add the current value to the chunk
  5. Return the modified array of chunks
  6. Initialize the reduction by passing an empty array

Currying based on chunkSize:

var chunk3 = function(array) {
    return chunk(3, array);
};

console.log(chunk3(['a', 'b', 'c', 'd', 'e']));
// prints [ [ 'a', 'b', 'c' ], [ 'd', 'e' ] ]

You can add the chunk() function to the global Array object:

_x000D_
_x000D_
Object.defineProperty(Array.prototype, 'chunk', {_x000D_
    value: function(chunkSize) {_x000D_
        return this.reduce(function(previous, current) {_x000D_
            var chunk;_x000D_
            if (previous.length === 0 || _x000D_
                    previous[previous.length -1].length === chunkSize) {_x000D_
                chunk = [];_x000D_
                previous.push(chunk);_x000D_
            }_x000D_
            else {_x000D_
                chunk = previous[previous.length -1];_x000D_
            }_x000D_
            chunk.push(current);_x000D_
            return previous;_x000D_
        }, []);_x000D_
    }_x000D_
});_x000D_
_x000D_
console.log(['a', 'b', 'c', 'd', 'e'].chunk(4));_x000D_
// prints [ [ 'a', 'b', 'c' 'd' ], [ 'e' ] ]
_x000D_
_x000D_
_x000D_


Use chunk from lodash

lodash.chunk(arr,<size>).forEach(chunk=>{
  console.log(chunk);
})

I tested the different answers into jsperf.com. The result is available there: https://web.archive.org/web/20150909134228/https://jsperf.com/chunk-mtds

And the fastest function (and that works from IE8) is this one:

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;
}

Here's a recursive solution that is tail call optimize.

_x000D_
_x000D_
const splitEvery = (n, xs, y=[]) =>_x000D_
  xs.length===0 ? y : splitEvery(n, xs.slice(n), y.concat([xs.slice(0, n)])) _x000D_
_x000D_
console.log(splitEvery(2, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]))
_x000D_
_x000D_
_x000D_


The one line in pure javascript:

_x000D_
_x000D_
function chunks(array, size) {
  return Array.apply(0,{length: Math.ceil(array.length / size)}).map((_, index) => array.slice(index*size, (index+1)*size))
}

// The following will group letters of the alphabet by 4
console.log(chunks([...Array(26)].map((x,i)=>String.fromCharCode(i + 97)), 4))
_x000D_
_x000D_
_x000D_


I created the following JSFiddle to demonstrate my approach to your question.

_x000D_
_x000D_
(function() {_x000D_
  // Sample arrays_x000D_
  var //elements = ["0", "1", "2", "3", "4", "5", "6", "7"],_x000D_
      elements = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "30", "31", "32", "33", "34", "35", "36", "37", "38", "39", "40", "41", "42", "43"];_x000D_
_x000D_
  var splitElements = [],_x000D_
      delimiter = 10; // Change this value as needed_x000D_
      _x000D_
  // parameters: array, number of elements to split the array by_x000D_
  if(elements.length > delimiter){_x000D_
   splitElements = splitArray(elements, delimiter);_x000D_
  }_x000D_
  else {_x000D_
   // No need to do anything if the array's length is less than the delimiter_x000D_
   splitElements = elements;_x000D_
  }_x000D_
  _x000D_
  //Displaying result in console_x000D_
  for(element in splitElements){_x000D_
   if(splitElements.hasOwnProperty(element)){_x000D_
     console.log(element + " | " + splitElements[element]);_x000D_
    }_x000D_
  }_x000D_
})();_x000D_
_x000D_
function splitArray(elements, delimiter) {_x000D_
  var elements_length = elements.length;_x000D_
_x000D_
  if (elements_length > delimiter) {_x000D_
    var myArrays = [], // parent array, used to store each sub array_x000D_
      first = 0, // used to capture the first element in each sub array_x000D_
      index = 0; // used to set the index of each sub array_x000D_
_x000D_
    for (var i = 0; i < elements_length; ++i) {_x000D_
      if (i % delimiter === 0) {_x000D_
       // Capture the first element of each sub array from the original array, when i is a modulus factor of the delimiter._x000D_
        first = i;_x000D_
      } else if (delimiter - (i % delimiter) === 1) {_x000D_
      // Build each sub array, from the original array, sliced every time the i one minus the modulus factor of the delimiter._x000D_
        index = (i + 1) / delimiter - 1;_x000D_
        myArrays[index] = elements.slice(first, i + 1);_x000D_
      }_x000D_
      else if(i + 1 === elements_length){_x000D_
       // Build the last sub array which contain delimiter number or less elements_x000D_
       myArrays[index + 1] = elements.slice(first, i + 1);_x000D_
      }_x000D_
    }_x000D_
    // Returned is an array of arrays_x000D_
    return myArrays;_x000D_
  }_x000D_
}
_x000D_
_x000D_
_x000D_

First of all, I have two examples: an array with less than eight elements, another with an array with more than eight elements (comment whichever one you do not want to use).

I then check for the size of the array, simple but essential to avoid extra computation. From here if the array meets the criteria (array size > delimiter) we move into the splitArray function.

The splitArray function takes in the delimiter (meaning 8, since that is what you want to split by), and the array itself. Since we are re-using the array length a lot, I am caching it in a variable, as well as the first and last.

first represents the position of the first element in an array. This array is an array made of 8 elements. So in order to determine the first element we use the modulus operator.

myArrays is the array of arrays. In it we will store at each index, any sub array of size 8 or below. This is the key strategy in the algorithm below.

index represents the index for the myArrays variable. Every time a sub array of 8 elements or less is to be stored, it needs to be stored in the corresponding index. So if we have 27 elements, that means 4 arrays. The first, second and third array will have 8 elements each. The last will have 3 elements only. So index will be 0, 1, 2, and 3 respectively.

The tricky part is simply figuring out the math and optimizing it as best as possible. For example else if (delimiter - (i % delimiter) === 1) this is to find the last element that should go in the array, when an array will be full (example: contain 10 elements).

This code works for every single scenario, you can even change the delimiter to match any array size you'd like to get. Pretty sweet right :-)

Any questions? Feel free to ask in the comments below.


Super late to the party but I solved a similar problem with the approach of using .join("") to convert the array to one giant string, then using regex to .match(/.{1,7}/) it into arrays of substrings of max length 7.

const arr = ['abc', 'def', 'gh', 'ijkl', 'm', 'nopq', 'rs', 'tuvwx', 'yz'];
const arrayOfSevens = arr.join("").match(/.{1,7}/g);
// ["abcdefg", "hijklmn", "opqrstu", "vwxyz"]

Would be interesting to see how this performs in a speed test against other methods


I just wrote this with the help of a groupBy function.

_x000D_
_x000D_
// utils_x000D_
const group = (source) => ({_x000D_
  by: (grouping) => {_x000D_
    const groups = source.reduce((accumulator, item) => {_x000D_
      const name = JSON.stringify(grouping(item));_x000D_
      accumulator[name] = accumulator[name] || [];_x000D_
      accumulator[name].push(item);_x000D_
      return accumulator;_x000D_
    }, {});_x000D_
_x000D_
    return Object.keys(groups).map(key => groups[key]);_x000D_
  }_x000D_
});_x000D_
_x000D_
const chunk = (source, size) => group(source.map((item, index) => ({ item, index })))_x000D_
.by(x => Math.floor(x.index / size))_x000D_
.map(x => x.map(v => v.item));_x000D_
_x000D_
_x000D_
// 103 items_x000D_
const arr = [6,2,6,6,0,7,4,9,3,1,9,6,1,2,7,8,3,3,4,6,8,7,6,9,3,6,3,5,0,9,3,7,0,4,1,9,7,5,7,4,3,4,8,9,0,5,1,0,0,8,0,5,8,3,2,5,6,9,0,0,1,5,1,7,0,6,1,6,8,4,9,8,9,1,6,5,4,9,1,6,6,1,8,3,5,5,7,0,8,3,1,7,1,1,7,6,4,9,7,0,5,1,0];_x000D_
_x000D_
const chunks = chunk(arr, 10);_x000D_
_x000D_
console.log(JSON.stringify(chunks));
_x000D_
_x000D_
_x000D_


Here's a solution using ImmutableJS, where items is an Immutable List and size is the required grouping size.

const partition = ((items, size) => {
  return items.groupBy((items, i) => Math.floor(i/size))
})

I prefer to use the splice method instead of slice. This solution uses the array length and chunk size to create a loop count and then loops over the array which gets smaller after every operation due to splicing in each step.

    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);

If you dont want to mutate the original array, you can clone the original array using the spread operator and then use that array to solve the problem.

    let clonedArray = [...OriginalArray]

EDIT: @mblase75 added more concise code to the earlier answer while I was writing mine, so I recommend going with his solution.

You could use code like this:

var longArray = ["Element 1","Element 2","Element 3", /*...*/];
var smallerArrays = []; // will contain the sub-arrays of 10 elements each
var arraySize = 10;
for (var i=0;i<Math.ceil(longArray.length/arraySize);i++) {
    smallerArrays.push(longArray.slice(i*arraySize,i*arraySize+arraySize));
}

Change the value of arraySize to change the maximum length of the smaller arrays.


Her is a simple solution using @Blazemonger solution

function array_chunk(arr, size){
    // initialize vars
    var i,
    j = arr.length,
    tempArray = [];
    // loop through and jump based on size
    for (i=0; i<j; i+=size) {
        // slice chunk of arr and push to tempArray
        tempArray.push(arr.slice(i,i+size));
    }
    // return temp array (chunck)
    return tempArray
}

This got the pipline flowing for me, hope this helps someone else out there. :)


Neat and clean easy to understand

 let nums = [1, 2, 3, 4, 5, 6, 7, 8, 9];
 let len = nums.length ;

    const chunkArr = (arr, chunkNo) => {
      let newArr = [];
      for(let i = 0; i < len; i++){
        if(nums[0] !== "" && nums[0] !== undefined ){
          let a = nums.splice(0,chunkNo) ; 
          newArr.push(a);
        }
      }
       return newArr ;
    }
    console.log(chunkArr(nums, 5));

I aimed at creating a simple non-mutating solution in pure ES6. Peculiarities in javascript make it necessary to fill the empty array before mapping :-(

function chunk(a, l) { 
    return new Array(Math.ceil(a.length / l)).fill(0)
        .map((_, n) => a.slice(n*l, n*l + l)); 
}

This version with recursion seem simpler and more compelling:

function chunk(a, l) { 
    if (a.length == 0) return []; 
    else return [a.slice(0, l)].concat(chunk(a.slice(l), l)); 
}

The ridiculously weak array functions of ES6 makes for good puzzles :-)


Here is a non-mutating solution using only recursion and slice().

const splitToChunks = (arr, chunkSize, acc = []) => (
    arr.length > chunkSize ?
        splitToChunks(
            arr.slice(chunkSize),
            chunkSize,
            [...acc, arr.slice(0, chunkSize)]
        ) :
        [...acc, arr]
);

Then simply use it like splitToChunks([1, 2, 3, 4, 5], 3) to get [[1, 2, 3], [4, 5]].

Here is a fiddle for you to try out: https://jsfiddle.net/6wtrbx6k/2/


ES6 spreads functional #ohmy #ftw

_x000D_
_x000D_
const chunk =_x000D_
  (size, xs) => _x000D_
    xs.reduce(_x000D_
      (segments, _, index) =>_x000D_
        index % size === 0 _x000D_
          ? [...segments, xs.slice(index, index + size)] _x000D_
          : segments, _x000D_
      []_x000D_
    );_x000D_
_x000D_
console.log( chunk(3, [1, 2, 3, 4, 5, 6, 7, 8]) );
_x000D_
_x000D_
_x000D_


# in coffeescript
# assume "ar" is the original array
# newAr is the new array of arrays

newAr = []
chunk = 10
for i in [0... ar.length] by chunk
   newAr.push ar[i... i+chunk]

# or, print out the elements one line per chunk
for i in [0... ar.length] by chunk
   console.log ar[i... i+chunk].join ' '

I recommend using lodash. Chunking is one of many useful functions there. Instructions:

npm i --save lodash

Include in your project:

import * as _ from 'lodash';

Usage:

const arrayOfElements = ["Element 1","Element 2","Element 3", "Element 4", "Element 5","Element 6","Element 7","Element 8","Element 9","Element 10","Element 11","Element 12"]
const chunkedElements = _.chunk(arrayOfElements, 10)

You can find my sample here: https://playcode.io/659171/


This is what i use, it might not be super fast, but it is compact and simple:

_x000D_
_x000D_
let chunksplit = (stream, size) => stream.reduce((chunks, item, idx, arr) => (idx % size == 0) ? [...chunks, arr.slice(idx, idx + size)] : chunks, []);_x000D_
//if the index is a multiple of the chunksize, add new array_x000D_
_x000D_
let testArray = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22];_x000D_
_x000D_
document.write(JSON.stringify( chunksplit(testArray, 5) ));_x000D_
//using JSON.stringify for the nested arrays to be shown
_x000D_
_x000D_
_x000D_


_x000D_
_x000D_
    const array = [86,133,87,133,88,133,89,133,90,133];_x000D_
    const new_array = [];_x000D_
_x000D_
 const chunksize = 2;_x000D_
    while (array.length) {_x000D_
     const chunk = array.splice(0,chunksize);_x000D_
     new_array.push(chunk);_x000D_
    }_x000D_
_x000D_
    console.log(new_array)
_x000D_
_x000D_
_x000D_


There could be many solution to this problem.

one of my fav is:

_x000D_
_x000D_
function chunk(array, size) {_x000D_
    const chunked = [];_x000D_
_x000D_
    for (element of array){_x000D_
        let last = chunked[chunked.length - 1];_x000D_
_x000D_
        if(last && last.length != size){_x000D_
            last.push(element)_x000D_
        }else{_x000D_
            chunked.push([element])_x000D_
        }_x000D_
    }_x000D_
   _x000D_
    return chunked;_x000D_
}_x000D_
_x000D_
_x000D_
function chunk1(array, size) {_x000D_
    const chunked = [];_x000D_
_x000D_
    let index = 0;_x000D_
_x000D_
    while(index < array.length){_x000D_
        chunked.push(array.slice(index,index+ size))_x000D_
        index += size;_x000D_
    }_x000D_
    return chunked;_x000D_
}_x000D_
_x000D_
console.log('chunk without slice:',chunk([1,2,3,4,5,5],2));_x000D_
console.log('chunk with use of slice funtion',chunk1([1,2,3,4,5,6],2))
_x000D_
_x000D_
_x000D_


There have been many answers but this is what I use:

const chunk = (arr, size) =>
  arr
    .reduce((acc, _, i) =>
      (i % size)
        ? acc
        : [...acc, arr.slice(i, i + size)]
    , [])

// USAGE
const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
chunk(numbers, 3)

// [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10]]

First, check for a remainder when dividing the index by the chunk size.

If there is a remainder then just return the accumulator array.

If there is no remainder then the index is divisible by the chunk size, so take a slice from the original array (starting at the current index) and add it to the accumulator array.

So, the returned accumulator array for each iteration of reduce looks something like this:

// 0: [[1, 2, 3]]
// 1: [[1, 2, 3]]
// 2: [[1, 2, 3]]
// 3: [[1, 2, 3], [4, 5, 6]]
// 4: [[1, 2, 3], [4, 5, 6]]
// 5: [[1, 2, 3], [4, 5, 6]]
// 6: [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
// 7: [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
// 8: [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
// 9: [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10]]

Here's another solution with the reduce() method, though slightly different from other examples. Hopefully my explanation is a bit clearer as well.

_x000D_
_x000D_
var arr = [0, 1, 2, 3, 4, 5, 6, 7];
var chunkSize = 3;

arr = arr.reduce((acc, item, idx) => {
  let group = acc.pop();
  if (group.length == chunkSize) {
    acc.push(group);
    group = [];
  }
  group.push(item);
  acc.push(group);
  return acc;
}, [[]]);

console.log(arr); //Prints [[0, 1, 2], [3, 4, 5], [6, 7]]
_x000D_
_x000D_
_x000D_


Explanation

We call a reducer which, for each item in the array, gets the last item of the accumulator with pop(). Remember that this item is an array which groups up to chunkSize number of items (3 in this example).

If, and only if, this group has the array length equal to chunksize we need to re-insert the group back into the accumulator and create a new group.

We then push the current item into our group array (which may already contain 0, 1 or 2 items from the previous steps). With the current item inserted into the group, we need to re-insert the group back into the larger collection.

The process will repeat until we've iterated through all items in arr.

Note that we have also provided the reducer with the starting value of an empty array inside an array with [[]].


If you are using Underscore JS, just use :

var result = _.chunk(arr,elements_per_chunk)

Most projects already use underscore as a dependency, anyways.


Array.prototype.sliceIntoChunks = function(chunkSize) {
                    var chunks = [];
                    var temparray = null;

                    for (var i = 0; i < this.length; i++) {
                        if (i % chunkSize === 0) {
                            temparray = new Array();
                            chunks.push(temparray);
                        }
                        temparray.push(this[i]);
                    }

                    return chunks;
                };

You can use as follows:

var myArray = ["A", "B", "C", "D", "E"];
var mySlicedArray = myArray.sliceIntoChunks(2);

Result:

mySlicedArray[0] = ["A", "B"];
mySlicedArray[1] = ["C", "D"];
mySlicedArray[2] = ["E"];

ONE-LINER

const chunk = (a,n)=>[...Array(Math.ceil(a.length/n))].map((_,i)=>a.slice(n*i,n+n*i));

For TypeScript

const chunk = <T>(arr: T[], size: number): T[][] =>
  [...Array(Math.ceil(arr.length / size))].map((_, i) =>
    arr.slice(size * i, size + size * i)
  );

DEMO

_x000D_
_x000D_
const chunk = (a,n)=>[...Array(Math.ceil(a.length/n))].map((_,i)=>a.slice(n*i,n+n*i));
document.write(JSON.stringify(chunk([1, 2, 3, 4], 2)));
_x000D_
_x000D_
_x000D_

Chunk By Number Of Groups

const part=(a,n)=>[...Array(n)].map((_,i)=>a.slice(i*Math.ceil(a.length/n),(i+1)*Math.ceil(a.length/n)));

For TypeScript

const part = <T>(a: T[], n: number): T[][] => {
  const b = Math.ceil(a.length / n);
  return [...Array(n)].map((_, i) => a.slice(i * b, (i + 1) * b));
};

DEMO

_x000D_
_x000D_
const part = (a, n) => {
    const b = Math.ceil(a.length / n);
    return [...Array(n)].map((_, i) => a.slice(i * b, (i + 1) * b));
};

document.write(JSON.stringify(part([1, 2, 3, 4, 5, 6], 2))+'<br/>');
document.write(JSON.stringify(part([1, 2, 3, 4, 5, 6, 7], 2)));
_x000D_
_x000D_
_x000D_


Here's a version with tail recursion and array destructuring.

Far from the fastest performance, but I'm just amused that js can do this now. Even if it isn't optimized for it :(

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]]

I changed BlazeMonger's slightly to use for a jQuery object..

var $list = $('li'),
    $listRows = [];


for (var i = 0, len = $list.length, chunk = 4, n = 0; i < len; i += chunk, n++) {
   $listRows[n] = $list.slice(i, i + chunk);
}

Old question: New answer! I actually was working with an answer from this question and had a friend improve on it! So here it is:

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]]

ES6 one-line approach based on Array.prototype reduce and push methods:

const doChunk = (list, size) => list.reduce((r, v) =>
  (!r.length || r[r.length - 1].length === size ?
    r.push([v]) : r[r.length - 1].push(v)) && r
, []);

console.log(doChunk([0,1,2,3,4,5,6,7,8,9,10,11,12], 5));
// [[0, 1, 2, 3, 4], [5, 6, 7, 8, 9], [10, 11, 12]]

I'd prefer to use splice method:

var chunks = function(array, size) {
  var results = [];
  while (array.length) {
    results.push(array.splice(0, size));
  }
  return results;
};

ES6 Generator version

function* chunkArray(array,size=1){
    var clone = array.slice(0);
    while (clone.length>0) 
      yield clone.splice(0,size); 
};
var a = new Array(100).fill().map((x,index)=>index);
for(const c of chunkArray(a,10)) 
    console.log(c);

Try this :

_x000D_
_x000D_
var oldArray =  ["Banana", "Orange", "Lemon", "Apple", "Mango", "Banana", "Orange", "Lemon", "Apple", "Mango", "Banana", "Orange", "Lemon", "Apple", "Mango", "Banana", "Orange", "Lemon", "Apple", "Mango", "Banana", "Orange", "Lemon", "Apple", "Mango"];_x000D_
_x000D_
var newArray = [];_x000D_
_x000D_
while(oldArray.length){_x000D_
    let start = 0;_x000D_
    let end = 10;_x000D_
    newArray.push(oldArray.slice(start, end));_x000D_
    oldArray.splice(start, end);_x000D_
 }_x000D_
 _x000D_
 console.log(newArray);
_x000D_
_x000D_
_x000D_


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 ] ]

Nowadays you can use lodash' chunk function to split the array into smaller arrays https://lodash.com/docs#chunk No need to fiddle with the loops anymore!


function chunk(arr, size) {
  var tempAr = [];
  var j=  0;
  for(var i =0 ;i<arr.length;i++){ 
    if(j==size || j==0){  
     tempAr.push(arr.slice(i,(i+size)));
      j=0;
      }j++;
  }
  return tempAr;
}

And this would be my contribution to this topic. I guess .reduce() is the best way.

_x000D_
_x000D_
var segment = (arr, n) => arr.reduce((r,e,i) => i%n ? (r[r.length-1].push(e), r)_x000D_
                                                    : (r.push([e]), r), []),_x000D_
        arr = Array.from({length: 31}).map((_,i) => i+1);_x000D_
        res = segment(arr,7);_x000D_
console.log(JSON.stringify(res));
_x000D_
_x000D_
_x000D_

But the above implementation is not very efficient since .reduce() runs through all arr function. A more efficient approach (very close to the fastest imperative solution) would be, iterating over the reduced (to be chunked) array since we can calculate it's size in advance by Math.ceil(arr/n);. Once we have the empty result array like Array(Math.ceil(arr.length/n)).fill(); the rest is to map slices of the arr array into it.

_x000D_
_x000D_
function chunk(arr,n){_x000D_
  var r = Array(Math.ceil(arr.length/n)).fill();_x000D_
  return r.map((e,i) => arr.slice(i*n, i*n+n));_x000D_
}_x000D_
_x000D_
arr = Array.from({length: 31},(_,i) => i+1);_x000D_
res = chunk(arr,7);_x000D_
console.log(JSON.stringify(res));
_x000D_
_x000D_
_x000D_


Created a npm package for this https://www.npmjs.com/package/array.chunk

var result = [];

for (var i = 0; i < arr.length; i += size) {
  result.push(arr.slice(i, size + i));
}
return result;

When using a TypedArray

var result = [];

for (var i = 0; i < arr.length; i += size) {
  result.push(arr.subarray(i, size + i));
}
return result;

Here's my approach using Coffeescript list comprehension. A great article detailing comprehensions in Coffeescript can be found here.

chunk: (arr, size) ->
    chunks = (arr.slice(index, index+size) for item, index in arr by size)
    return chunks

Using generators

_x000D_
_x000D_
function* 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]]
_x000D_
_x000D_
_x000D_


results = []
chunk_size = 10
while(array.length > 0){
   results.push(array.splice(0, chunk_size))
}

This is the most efficient and straight-forward solution I could think of:

function chunk(array, chunkSize) {
    let chunkCount = Math.ceil(array.length / chunkSize);
    let chunks = new Array(chunkCount);
    for(let i = 0, j = 0, k = chunkSize; i < chunkCount; ++i) {
        chunks[i] = array.slice(j, k);
        j = k;
        k += chunkSize;
    }
    return chunks;
}

Try to avoid mucking with native prototypes, including Array.prototype, if you don't know who will be consuming your code (3rd parties, coworkers, yourself at a later date, etc.).

There are ways to safely extend prototypes (but not in all browsers) and there are ways to safely consume objects created from extended prototypes, but a better rule of thumb is to follow the Principle of Least Surprise and avoid these practices altogether.

If you have some time, watch Andrew Dupont's JSConf 2011 talk, "Everything is Permitted: Extending Built-ins", for a good discussion about this topic.

But back to the question, while the solutions above will work, they are overly complex and requiring unnecessary computational overhead. Here is my solution:

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;

Here's a ES6 version using reduce

_x000D_
_x000D_
var perChunk = 2 // items per chunk    _x000D_
_x000D_
var inputArray = ['a','b','c','d','e']_x000D_
_x000D_
var result = inputArray.reduce((resultArray, item, index) => { _x000D_
  const chunkIndex = Math.floor(index/perChunk)_x000D_
_x000D_
  if(!resultArray[chunkIndex]) {_x000D_
    resultArray[chunkIndex] = [] // start a new chunk_x000D_
  }_x000D_
_x000D_
  resultArray[chunkIndex].push(item)_x000D_
_x000D_
  return resultArray_x000D_
}, [])_x000D_
_x000D_
console.log(result); // result: [['a','b'], ['c','d'], ['e']]
_x000D_
_x000D_
_x000D_

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
}, [])

The following ES2015 approach works without having to define a function and directly on anonymous arrays (example with chunk size 2):

[11,22,33,44,55].map((_, i, all) => all.slice(2*i, 2*i+2)).filter(x=>x.length)

If you want to define a function for this, you could do it as follows (improving on K._'s comment on Blazemonger's answer):

const array_chunks = (array, chunk_size) => array
    .map((_, i, all) => all.slice(i*chunk_size, (i+1)*chunk_size))
    .filter(x => x.length)

my trick is to use parseInt(i/chunkSize) and parseInt(i%chunkSize) and then filling the array

_x000D_
_x000D_
// filling items_x000D_
let array = [];_x000D_
for(let i = 0; i< 543; i++)_x000D_
  array.push(i);_x000D_
 _x000D_
 // printing the splitted array_x000D_
 console.log(getSplittedArray(array, 50));_x000D_
 _x000D_
 // get the splitted array_x000D_
 function getSplittedArray(array, chunkSize){_x000D_
  let chunkedArray = [];_x000D_
  for(let i = 0; i<array.length; i++){_x000D_
    try{_x000D_
      chunkedArray[parseInt(i/chunkSize)][parseInt(i%chunkSize)] = array[i];_x000D_
    }catch(e){_x000D_
      chunkedArray[parseInt(i/chunkSize)] = [];_x000D_
      chunkedArray[parseInt(i/chunkSize)][parseInt(i%chunkSize)] = array[i];_x000D_
    }_x000D_
  }_x000D_
  return chunkedArray;_x000D_
 }
_x000D_
_x000D_
_x000D_


In case this is useful to anyone, this can be done very simply in RxJS 6:

const arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16];
from(arr).pipe(bufferCount(3)).subscribe(chunk => console.log(chunk));

Outputs: [1, 2, 3] [4, 5, 6] [7, 8, 9] [10, 11, 12] [13, 14, 15] [16]


Ok, let's start with a fairly tight one:

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); });
}

Which is used like this:

chunk([1,2,3,4,5,6,7], 2);

Then we have this tight reducer function:

function chunker(p, c, i) {
    (p[i/this|0] = p[i/this|0] || []).push(c);
    return p;
}

Which is used like this:

[1,2,3,4,5,6,7].reduce(chunker.bind(3),[]);

Since a kitten dies when we bind this to a number, we can do manual currying like this instead:

// 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;
   };
}

Which is used like this:

[1,2,3,4,5,6,7].reduce(chunker(3),[]);

Then the still pretty tight function which does it all in one go:

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);

Hi try this -

 function split(arr, howMany) {
        var newArr = []; start = 0; end = howMany;
        for(var i=1; i<= Math.ceil(arr.length / howMany); i++) {
            newArr.push(arr.slice(start, end));
            start = start + howMany;
            end = end + howMany
        }
        console.log(newArr)
    }
    split([1,2,3,4,55,6,7,8,8,9],3)

One more solution using Array.prototype.reduce():

_x000D_
_x000D_
const chunk = (array, size) =>
  array.reduce((acc, _, i) => {
    if (i % size === 0) acc.push(array.slice(i, i + size))
    return acc
  }, [])

// Usage:
const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
const chunked = chunk(numbers, 3)
console.log(chunked)
_x000D_
_x000D_
_x000D_

This solution is very similar to the solution by Steve Holgado. However, because this solution doesn't utilize array spreading and doesn't create new arrays in the reducer function, it's faster (see jsPerf test) and subjectively more readable (simpler syntax) than the other solution.

At every nth iteration (where n = size; starting at the first iteration), the accumulator array (acc) is appended with a chunk of the array (array.slice(i, i + size)) and then returned. At other iterations, the accumulator array is returned as-is.

If size is zero, the method returns an empty array. If size is negative, the method returns broken results. So, if needed in your case, you may want to do something about negative or non-positive size values.


If speed is important in your case, a simple for loop would be faster than using reduce() (see the jsPerf test), and some may find this style more readable as well:

function chunk(array, size) {
  // This prevents infinite loops
  if (size < 1) throw new Error('Size must be positive')

  const result = []
  for (let i = 0; i < array.length; i += size) {
    result.push(array.slice(i, i + size))
  }
  return result
}

For a functional solution, using Ramda:

Where popularProducts is your input array, 5 is the chunk size

_x000D_
_x000D_
import splitEvery from 'ramda/src/splitEvery'_x000D_
_x000D_
splitEvery(5, popularProducts).map((chunk, i) => {_x000D_
// do something with chunk_x000D_
_x000D_
})
_x000D_
_x000D_
_x000D_


I solved it like this:

const chunks = [];
const chunkSize = 10;
for (let i = 0; i < arrayToSplit.length; i += chunkSize) {
  const tempArray = arrayToSplit.slice(i, i + chunkSize);
  chunks.push(tempArray);
}

You can take this ES6 chunk function, which is easy to use:

_x000D_
_x000D_
const chunk = (array, size) =>
  Array.from({length: Math.ceil(array.length / size)}, (value, index) => array.slice(index * size, index * size + size));

const itemsPerChunk = 3;
const inputArray = ['a', 'b', 'c', 'd', 'e', 'f', 'g'];

const newArray = chunk(inputArray, itemsPerChunk);
console.log(newArray.length); // 3,

document.write(JSON.stringify(newArray)); //  [ [ 'a', 'b', 'c' ], [ 'd', 'e', 'f' ], [ 'g' ] ]
_x000D_
_x000D_
_x000D_


Modified from an answer by dbaseman: https://stackoverflow.com/a/10456344/711085

_x000D_
_x000D_
Object.defineProperty(Array.prototype, 'chunk_inefficient', {_x000D_
  value: function(chunkSize) {_x000D_
    var array = this;_x000D_
    return [].concat.apply([],_x000D_
      array.map(function(elem, i) {_x000D_
        return i % chunkSize ? [] : [array.slice(i, i + chunkSize)];_x000D_
      })_x000D_
    );_x000D_
  }_x000D_
});_x000D_
_x000D_
console.log(_x000D_
  [1, 2, 3, 4, 5, 6, 7].chunk_inefficient(3)_x000D_
)_x000D_
// [[1, 2, 3], [4, 5, 6], [7]]
_x000D_
_x000D_
_x000D_


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:

_x000D_
_x000D_
// refresh page if experimenting and you already defined Array.prototype.chunk_x000D_
_x000D_
Object.defineProperty(Array.prototype, 'chunk', {_x000D_
  value: function(chunkSize) {_x000D_
    var R = [];_x000D_
    for (var i = 0; i < this.length; i += chunkSize)_x000D_
      R.push(this.slice(i, i + chunkSize));_x000D_
    return R;_x000D_
  }_x000D_
});_x000D_
_x000D_
console.log(_x000D_
  [1, 2, 3, 4, 5, 6, 7].chunk(3)_x000D_
)
_x000D_
_x000D_
_x000D_


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));
}});

Here is neat & optimised implemention of chunk() function. Assuming default chunk size is 10.

var chunk = function(list, chunkSize) {
  if (!list.length) {
    return [];
  }
  if (typeof chunkSize === undefined) {
    chunkSize = 10;
  }

  var i, j, t, chunks = [];
  for (i = 0, j = list.length; i < j; i += chunkSize) {
    t = list.slice(i, i + chunkSize);
    chunks.push(t);
  }

  return chunks;
};

//calling function
var list = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12];
var chunks = chunk(list);

One-liner in ECMA 6

const [list,chuckSize] = [[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15], 6]

[...Array(Math.ceil(list.length / chuckSize))].map(_ => list.splice(0,chuckSize))

This should be straightforward answer without many mathematical complications.

function chunkArray(array, sizeOfTheChunkedArray) {
  const chunked = [];

  for (let element of array) {
    const last = chunked[chunked.length - 1];

    if(!last || last.length === sizeOfTheChunkedArray) {
      chunked.push([element])
    } else {
      last.push(element);
    }
  }
  return chunked;
}

Using Array.prototype.splice() and splice it until the array has element.

_x000D_
_x000D_
Array.prototype.chunk = function(size) {
    let result = [];
    
    while(this.length) {
        result.push(this.splice(0, size));
    }
        
    return result;
}

const arr = [1, 2, 3, 4, 5, 6, 7, 8, 9];
console.log(arr.chunk(2));
_x000D_
_x000D_
_x000D_

Update

Array.prototype.splice() populates the original array and after performing the chunk() the original array (arr) becomes [].

So if you want to keep the original array untouched, then copy and keep the arr data into another array and do the same thing.

_x000D_
_x000D_
Array.prototype.chunk = function(size) {
  let data = [...this];  
  let result = [];
    
    while(data.length) {
        result.push(data.splice(0, size));
    }

    return result;
}

const arr = [1, 2, 3, 4, 5, 6, 7, 8, 9];
console.log('chunked:', arr.chunk(2));
console.log('original', arr);
_x000D_
_x000D_
_x000D_

P.S: Thanks to @mts-knn for mentioning the matter.


I think this a nice recursive solution with ES6 syntax:

_x000D_
_x000D_
const chunk = function(array, size) {_x000D_
  if (!array.length) {_x000D_
    return [];_x000D_
  }_x000D_
  const head = array.slice(0, size);_x000D_
  const tail = array.slice(size);_x000D_
_x000D_
  return [head, ...chunk(tail, size)];_x000D_
};_x000D_
_x000D_
console.log(chunk([1,2,3], 2));
_x000D_
_x000D_
_x000D_


Examples related to javascript

need to add a class to an element How to make a variable accessible outside a function? Hide Signs that Meteor.js was Used How to create a showdown.js markdown extension Please help me convert this script to a simple image slider Highlight Anchor Links when user manually scrolls? Summing radio input values How to execute an action before close metro app WinJS javascript, for loop defines a dynamic variable name Getting all files in directory with ajax

Examples related to arrays

PHP array value passes to next row Use NSInteger as array index How do I show a message in the foreach loop? Objects are not valid as a React child. If you meant to render a collection of children, use an array instead Iterating over arrays in Python 3 Best way to "push" into C# array Sort Array of object by object field in Angular 6 Checking for duplicate strings in JavaScript array what does numpy ndarray shape do? How to round a numpy array?

Examples related to split

Parameter "stratify" from method "train_test_split" (scikit Learn) Pandas split DataFrame by column value How to split large text file in windows? Attribute Error: 'list' object has no attribute 'split' Split function in oracle to comma separated values with automatic sequence How would I get everything before a : in a string Python Split String by delimiter position using oracle SQL JavaScript split String with white space Split a String into an array in Swift? Split pandas dataframe in two if it has more than 10 rows