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?
ES6 Generator version
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 :-(
This version with recursion seem simpler and more compelling:
The ridiculously weak array functions of ES6 makes for good puzzles :-)
This is the most efficient and straight-forward solution I could think of:
I created the following JSFiddle to demonstrate my approach to your question.
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 thesplitArray
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 thefirst
andlast
.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 themyArrays
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. Soindex
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.
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:
If you use EcmaScript version >= 5.1, you can implement a functional version of
chunk()
using array.reduce() that has O(N) complexity:Explanation of each
// nbr
above:chunkSize
itemsCurrying based on
chunkSize
:You can add the
chunk()
function to the globalArray
object: