How to split a long array into smaller arrays, with JavaScript

JavascriptJqueryArraysLoops

Javascript Problem Overview


I have an array of e-mails (it can be just 1 email, or 100 emails), and I need to send the array with an ajax request (that I know how to do), but I can only send an array that has 10 or less e-mails in it. So if there is an original array of 20 e-mails I will need to split them up into 2 arrays of 10 each. or if there are 15 e-mails in the original array, then 1 array of 10, and another array of 5. I'm using jQuery, what would be the best way to do this?

Javascript Solutions


Solution 1 - Javascript

Don't use jquery...use plain javascript

var a = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15];

var b = a.splice(0,10);

//a is now [11,12,13,14,15];
//b is now [1,2,3,4,5,6,7,8,9,10];

You could loop this to get the behavior you want.

var a = YOUR_ARRAY;
while(a.length) {
    console.log(a.splice(0,10));
}

This would give you 10 elements at a time...if you have say 15 elements, you would get 1-10, the 11-15 as you wanted.

Solution 2 - Javascript

var size = 10; var arrayOfArrays = [];
for (var i=0; i<bigarray.length; i+=size) {
     arrayOfArrays.push(bigarray.slice(i,i+size));
}
console.log(arrayOfArrays);

Unlike splice(), slice() is non-destructive to the original array.

Solution 3 - Javascript

Just loop over the array, splicing it until it's all consumed.




var a = ['a','b','c','d','e','f','g']
, chunk




while (a.length > 0) {




chunk = a.splice(0,3)




console.log(chunk)




}


output


[ 'a', 'b', 'c' ]
[ 'd', 'e', 'f' ]
[ 'g' ]


Solution 4 - Javascript

You can use lodash: https://lodash.com/docs

_.chunk(['a', 'b', 'c', 'd'], 2);
// → [['a', 'b'], ['c', 'd']]

Solution 5 - Javascript

Array.reduce could be inefficient for large arrays, especially with the mod operator. I think a cleaner (and possibly easier to read) functional solution would be this:

const chunkArray = (arr, size) =>
  arr.length > size
    ? [arr.slice(0, size), ...chunkArray(arr.slice(size), size)]
    : [arr];

Solution 6 - Javascript

Assuming you don't want to destroy the original array, you can use code like this to break up the long array into smaller arrays which you can then iterate over:

var longArray = [];   // assume this has 100 or more email addresses in it
var shortArrays = [], i, len;

for (i = 0, len = longArray.length; i < len; i += 10) {
    shortArrays.push(longArray.slice(i, i + 10));
}

// now you can iterate over shortArrays which is an 
// array of arrays where each array has 10 or fewer 
// of the original email addresses in it

for (i = 0, len = shortArrays.length; i < len; i++) {
    // shortArrays[i] is an array of email addresss of 10 or less
}

Solution 7 - Javascript

As a supplement to @jyore's answer, and in case you still want to keep the original array:

var originalArray = [1,2,3,4,5,6,7,8];

var splitArray = function (arr, size) {

  var arr2 = arr.slice(0),
      arrays = [];

  while (arr2.length > 0) {
      arrays.push(arr2.splice(0, size));
  }

  return arrays;
}

splitArray(originalArray, 2);
// originalArray is still = [1,2,3,4,5,6,7,8];

Solution 8 - Javascript

Another implementation:

const arr = ["H", "o", "w", " ", "t", "o", " ", "s", "p", "l", "i", "t", " ", "a", " ", "l", "o", "n", "g", " ", "a", "r", "r", "a", "y", " ", "i", "n", "t", "o", " ", "s", "m", "a", "l", "l", "e", "r", " ", "a", "r", "r", "a", "y", "s", ",", " ", "w", "i", "t", "h", " ", "J", "a", "v", "a", "S", "c", "r", "i", "p", "t"];

const size = 3; 
const res = arr.reduce((acc, curr, i) => {
  if ( !(i % size)  ) {    // if index is 0 or can be divided by the `size`...
    acc.push(arr.slice(i, i + size));   // ..push a chunk of the original array to the accumulator
  }
  return acc;
}, []);

// => [["H", "o", "w"], [" ", "t", "o"], [" ", "s", "p"], ["l", "i", "t"], [" ", "a", " "], ["l", "o", "n"], ["g", " ", "a"], ["r", "r", "a"], ["y", " ", "i"], ["n", "t", "o"], [" ", "s", "m"], ["a", "l", "l"], ["e", "r", " "], ["a", "r", "r"], ["a", "y", "s"], [",", " ", "w"], ["i", "t", "h"], [" ", "J", "a"], ["v", "a", "S"], ["c", "r", "i"], ["p", "t"]]

NB - This does not modify the original array.

Or, if you prefer a functional, 100% immutable (although there's really nothing bad in mutating in place like done above) and self-contained method:

function splitBy(size, list) {
  return list.reduce((acc, curr, i, self) => {
    if ( !(i % size)  ) {  
      return [
          ...acc,
          self.slice(i, i + size),
        ];
    }
    return acc;
  }, []);
}

Solution 9 - Javascript

I would like to share my solution as well. It's a little bit more verbose but works as well.

var data = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15];

var chunksize = 4;


var chunks = [];

data.forEach((item)=>{
  if(!chunks.length || chunks[chunks.length-1].length == chunksize)
  chunks.push([]);

  chunks[chunks.length-1].push(item);
});

console.log(chunks);

Output (formatted):

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

Solution 10 - Javascript

You can start with an empty array and push inside it sections with your desired range from the original array at the same time you are subtracting from your original array until is empty.

const originalArr = [1,2,3,4,5,6,7,8,9,10,11];
const splittedArray = [];
  while (originalArr.length > 0) {
    splittedArray.push(originalArr.splice(0,range));  
  }

output for range 3

splittedArray === [[1,2,3][4,5,6][7,8,9][10,11]]

output for range 4

splittedArray === [[1,2,3,4][5,6,7,8][9,10,11]]

This is also good for a fronted pagination if want.

Solution 11 - Javascript

Another method:

var longArray = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
var size = 2;

var newArray = new Array(Math.ceil(longArray.length / size)).fill("")
    .map(function() { return this.splice(0, size) }, longArray.slice());

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

This doesn't affect the original array as a copy, made using slice, is passed into the 'this' argument of map.

Solution 12 - Javascript

Another implementation, using Array.reduce (I think it’s the only one missing!):

const splitArray = (arr, size) =>
{
    if (size === 0) {
        return [];
    }

    return arr.reduce((split, element, index) => {
        index % size === 0 ? split.push([element]) : split[Math.floor(index / size)].push(element);
        return split;
    }, []);
};

As many solutions above, this one’s non-destructive. Returning an empty array when the size is 0 is just a convention. If the if block is omitted you get an error, which might be what you want.

Solution 13 - Javascript

More compact:

const chunk = (xs, size) =>
  xs.map((_, i) =>
    (i % size === 0 ? xs.slice(i, i + size) : null)).filter(Boolean);
    
// Usage:
const sampleArray = new Array(33).fill(undefined).map((_, i) => i);

console.log(chunk(sampleArray, 5));

Solution 14 - Javascript

You can take a look at this code . Simple and Effective .

function chunkArrayInGroups(array, unit) {
var results = [],
length = Math.ceil(array.length / unit);

for (var i = 0; i < length; i++) {
	results.push(array.slice(i * unit, (i + 1) * unit));
}
 return results;
}

chunkArrayInGroups(["a", "b", "c", "d"], 2);

Solution 15 - Javascript

Here is a simple one liner

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

Solution 16 - Javascript

function chunkArrayInGroups(arr, size) {
    var newArr=[];

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

}

chunkArrayInGroups([0, 1, 2, 3, 4, 5, 6], 3);

Solution 17 - Javascript

as a function

var arrayChunk = function (array, chunkSize) {
            var arrayOfArrays = [];

            if (array.length <= chunkSize) {
                arrayOfArrays.push(array);
            } else {
                for (var i=0; i<array.length; i+=chunkSize) {
                    arrayOfArrays.push(array.slice(i,i+chunkSize));
                }
            }
            return arrayOfArrays;
        }

to use

arrayChunk(originalArray, 10) //10 being the chunk size.

Solution 18 - Javascript

using recursion

let myArr = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16];
let size = 4; //Math.sqrt(myArr.length); --> For a n x n matrix
let tempArr = [];
function createMatrix(arr, i) {
    if (arr.length !== 0) {
      if(i % size == 0) {
        tempArr.push(arr.splice(0,size))
      } 
      createMatrix(arr, i - 1)
    }
}
createMatrix(myArr, myArr.length);
console.log(tempArr);

Note: The existing array i.e. myArr will be modified.

Solution 19 - Javascript

using prototype we can set directly to array class

Array.prototype.chunk = function(n) {
  if (!this.length) {
    return [];
  }
  return [this.slice(0, n)].concat(this.slice(n).chunk(n));
};
console.log([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15].chunk(5));

Solution 20 - Javascript

If you want a method that doesn't modify the existing array, try this:

let oldArray = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15];
let newArray = [];
let size = 3; // Size of chunks you are after
let j = 0; // This helps us keep track of the child arrays

for (var i = 0; i < oldArray.length; i++) {
  if (i % size === 0) {
    j++
  }
  if(!newArray[j]) newArray[j] = [];
  newArray[j].push(oldArray[i])
}

Solution 21 - Javascript

function chunkArrayInGroups(arr, size) {
    var newArr=[];
  
    for (var i=0; arr.length>size; i++){
    newArr.push(arr.splice(0,size));
    }
    newArr.push(arr.slice(0));
    return newArr;
  
}

chunkArrayInGroups([0, 1, 2, 3, 4, 5, 6], 3);

Solution 22 - Javascript

let original = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14];
let size = 5;
let fragments = Array.from(Array(Math.ceil(a.length / size))).map((_,index) => a.slice(index * size,(index + 1) * size))

Solution 23 - Javascript

You can use the following code to achieve the required functionality

const splitter = (arr, splitBy, cache = []) => {
        const tmp = [...arr]
        while (tmp.length) cache.push(tmp.splice(0, splitBy))
        return cache
}
const split = splitter([0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21], 10)
console.log(split); 

Notice, it was an array of length 22 then the splitter function splits it into 2 smaller arrays of 10 items and 1 array of 2 items.

Solution 24 - Javascript

let a = [1, 2, 3, 4, 6, 7, 8, 9, 10, 11];
let _splitCount = 3;

let b = a.reduce((acc, curr, index) => {
  if (index % _splitCount === 0) {
    acc.push([curr]);
  } else {
    acc[acc.length - 1].push(curr);
  }
  return acc;
}, []);

this is the easy solution i think❤️

Solution 25 - Javascript

Using ES6 Generators

Late to the party, but ES6 generators opened up another neat way to achieve what is asked for.

/**
 * Returns chunks of size n.
 * @param {Array<any>} array any array
 * @param {number} n size of chunk 
 */
function* chunks(array, n){
  for(let i = 0; i < array.length; i += n) yield array.slice(i, i + n);
}

const result = [...chunks([1, 2, 3, 4, 5, 6, 7, 8 , 9, 10], 3)];
console.log(result);

.as-console-wrapper { max-height: 100% !important; top: 0; }

Make it work for infinite Generators

Using the same idea you can create a generator which can also generate an infinite amount of n-sized chunks from values retrieved from another (possibly infinite) generator function. This can be very handy to lazy-generate values once they are required which significantly reduces the required memory or it can even be used to generate a possibly infinite/ unknown number of chunks.

Here an example which uses two generators.

  • nextNaturalNumber() is an infinite generator which always returns the next natural number. I am using the ES2020 bigint datatype here so there is no restriction (by JavaScript) for the size of the value.
  • chunksFromIterable() creates n-sized chunks from an possibly infinite iterable.

/**
 * Returns chunks of size n for a possibly infinite iterator.
 * n must be >= 1
 * @param {Iterable<any>} iterable any array
 * @param {number} n size of chunk for n >= 1
 */
 function* chunksFromIterable(iterable, n){
  let arr = [];
  let i = n;
  for (const value of iterable) {
    if(i <= 0) {
      // another chunk of size n is filled => return chunk
      yield arr;
      arr = []; // create new empty array
      i = n; 
    };
    arr.push(value);
    i--;
  }
  // in case the iterable is not infinite check if there are still values in the array and return them if necessary
  if(arr.length > 0) yield arr;
}

/**
 * Infinite iterator which always gets the next natural number.
 */
function* nextNaturalNumber(){
  let i = 0n;
  while(true) {
    i += 1n;
    yield i;
  }
}

console.log("Finite iterable:");
// this version can now be used using the for ... of loop
for(const threeNaturalNumbers of chunksFromIterable([1, 2, 3, 4, 5, 6, 7, 8 , 9, 10], 3)){
  console.log(threeNaturalNumbers);
}

console.log("Infinite iterable:");
// and it can also be used for this infinite generator
for(const threeNaturalNumbers of chunksFromIterable(nextNaturalNumber(), 3)){
  printBigIntArray(threeNaturalNumbers);
  if(threeNaturalNumbers[0] > 30) break; // end here to avoid an infinite loop
}

// helper function to print array of bigints as this does not seem to be working for snippets
function printBigIntArray(arr){
  console.log(`[${arr.join(", ")}]`);
}

.as-console-wrapper { max-height: 100% !important; top: 0; }

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionBillView Question on Stackoverflow
Solution 1 - JavascriptjyoreView Answer on Stackoverflow
Solution 2 - JavascriptBlazemongerView Answer on Stackoverflow
Solution 3 - JavascriptClaudioView Answer on Stackoverflow
Solution 4 - JavascriptAlexander ParamonovView Answer on Stackoverflow
Solution 5 - Javascripttawnos178View Answer on Stackoverflow
Solution 6 - Javascriptjfriend00View Answer on Stackoverflow
Solution 7 - JavascriptJustinView Answer on Stackoverflow
Solution 8 - JavascriptAurelioView Answer on Stackoverflow
Solution 9 - JavascriptFilipe NicoliView Answer on Stackoverflow
Solution 10 - JavascriptBogdanView Answer on Stackoverflow
Solution 11 - JavascriptAFurlepaView Answer on Stackoverflow
Solution 12 - JavascriptAlfView Answer on Stackoverflow
Solution 13 - JavascriptdzucView Answer on Stackoverflow
Solution 14 - JavascriptSubhankarView Answer on Stackoverflow
Solution 15 - JavascriptReduView Answer on Stackoverflow
Solution 16 - JavascriptRidwanullah IbrahimView Answer on Stackoverflow
Solution 17 - JavascriptClintView Answer on Stackoverflow
Solution 18 - JavascriptSiddharth YadavView Answer on Stackoverflow
Solution 19 - JavascriptAmitNayekView Answer on Stackoverflow
Solution 20 - JavascriptRyanView Answer on Stackoverflow
Solution 21 - JavascriptzgthompsonView Answer on Stackoverflow
Solution 22 - JavascriptKhaled SayedView Answer on Stackoverflow
Solution 23 - JavascriptAbdullah AnsariView Answer on Stackoverflow
Solution 24 - JavascriptRaslaView Answer on Stackoverflow
Solution 25 - JavascriptMushroomatorView Answer on Stackoverflow