We're live-coding on Twitch! Join us!

This article marks the beginning of our array manipulation algorithms. In this article, we explore different techniques to chunk (split) an array into smaller units.

Array chunking is a technique used to split very large arrays into smaller groups(sizes) usually for easier manipulation and presentation.

We will learn more array manipulation techniques in our solutions as well as evaluate their performance and examine the practicality of this challenge.

Ready? Let's go!

You should already have your development environment setup for this course. Open the cloned repository and inside the Beginner folder, navigate to the chunkArray folder. Our work for this challenge will be done in here. Make sure to follow along in the index-START.js file.

The Challenge

Given an array and a chunk size, divide the array into many sub-arrays where each sub-array has the specified length. E.g

chunkArray([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13], 5)
// should return [[1, 2, 3, 4, 5], [6, 7, 8, 9, 10], [11, 12, 13]]

Algorithmic Thinking

From the challenge statement above, our function will receive two parameters, namely; the array to be split and the size of each chunk.

The size here refers to the maximum number of elements in each new sub-array.

Thus, we are expected to split the large array into smaller groups of the specified size. In the challenge sample, we split the array of 13 elements into smaller groups of 5, with the last group having only 3 elements because the elements from the supplied array have been exhausted.

In the same manner, we are to write a function that goes through the elements of the array received and split it into groups as specified by the size passed in.

Pretty straight forward, right? I think so too. Code Implementation We will now consider four approaches that utilize various techniques in solving this challenge. They are:

  • Looping through the array
  • Iterating with the number of chunks
  • Using .slice()
  • Recursion

Let's now examine them one at a time.

Looping Through the Array

In this approach, we loop through the array using a for…of loop as we manually break it down into smaller groups.

function chunkArray(array, size) {
    let result = []
    for (value of array){
        let lastArray = result[result.length -1 ]
        if(!lastArray || lastArray.length == size){
            result.push([value])
        } else{
            lastArray.push(value)
        }
    }
    return result
}

We initialize an empty array result with which we use to store every smaller group(chunk) that is created. Our intention here is to add each element to a group(sub-array) within our result array until all elements have been assigned.

Within the for…of loop, we use an if statement to check if our result array is currently empty or if the last group(sub-array) created is complete i.e already of the specified size .

If it is, we create a new group(sub-array) with the current value as an element and push it into the result array. If it isn't, we retrieve the last array from result and push the current value into it until the group is complete(i.e the required size is reached).

At the end, we return result which is an array of all the groups(sub-arrays) created throughout the iteration.

Looping Through the Number of Chunks

This is a more concise approach to chunking(grouping) the elements of an array. Here, we use the .splice() method to extract elements of the specified size from the array that is received.

The **.splice()** method is used to modify the content of an array by removing or replacing elements.

It receives two parameters: the starting index and the number of elements from that point to be extracted and returned.

function chunkArray(array, size) {
    let result = []
    let arrayCopy = [...array]
    while (arrayCopy.length > 0) {
        result.push(arrayCopy.splice(0, size))
    }
    return result
}

Because .splice() element manipulates the array in place (i.e it changes the received array directly), we use the spread operator to create a copy which we call arrayCopy so that our operations do not affect the data that is received.

It is from this copy that we continuously extract elements of the specified size using a while loop that will continue to execute for as long as the length of the arrayCopy is greater than 0.

Each sub-array created is then added to the result by calling the .push() method.

At the end, we return the result which is an array of all the groups(sub-arrays) that were created.

In the context of the sample above, we have an array of 13 elements to be grouped in five. Using the **.splice()** method, we start at the beginning(starting index of 0) and extract the first five elements from it into a new array which we now add to our **result** and repeat the process on the remaining 8. This process will continue to run for as long as there are still elements in the array i.e the length of the array is greater than 0.

Using .slice()

The .slice() method is used to extract a portion of an array starting from the specified beginning to end without modifying the original array. It returns a new array containing all elements from the starting index till the end index without including the item at the end index.

In the code snippet below, we use a for-loop to iterate through the array while repeatedly slicing off groups(chunks) of the specified size using the .slice() method. We increment the iterator by the specified size on each iteration in order to start each new group from where the previous one ended.

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

Again, we accumulate each group in our result array and then return it at the end of the iteration.

Let’s see one final solution.

Recursion

In this approach, we consistently reduce the problem set(i.e the size of the array) by slicing off chunks of the required size until all elements within the array have been grouped. To this effect, we add a conditional at the beginning to serve as the terminating condition such that when the number of remaining elements is less than or equal to the specified size, we simply return all the remaining elements as one group.

function chunkArray(array, size) {
   if(array.length <= size){
       return [array]
   }
   return [array.slice(0,size), ...chunkArray(array.slice(size), size)]
}

Notice that we use the .slice() method here to extract portions of the array as chunks as well as reduce the size of the original array continuously until the terminating condition is met.

All done! Let’s test our solutions. Testing

Testing Correctness with Jest

To carry out the tests for each solution above, run the command below in your terminal:

npm run test chunkArray
  • Looping through the array

  • Iterating with the number of chunks

  • Using .slice()

  • Recursion

Yippee!!!** We passed all tests**. Now, let’s evaluate performance.

Testing Performance with JSPerf

Here, we run a performance test on all four solutions explored above. The image below reveals the result.

After comparing all four solutions, we find that the .slice() method is the fastest of all implementations. It is followed by the recursive approach which is 46% slower.

Practical Application

This challenge is often encountered in coding interviews. In addition, the techniques explored herein are also applicable to batch data processing in real world applications.

That is, when processing very a large data-set listed as one large array, one could use this technique for breaking such data into smaller groups to be processed or presented in batches. This may bring the idea of pagination of lazy-loading to mind although there are usually more sophisticated ways to implement these.

One practical use case may be in developing a quiz app where questions are to be presented in groups of a specified number or size. One could retrieve all questions at once but chunk them into the desired size for each group for presentation of perhaps only five at a time.

Conclusion

We have now considered four major ways to chunk a given array into smaller arrays of the specified size. We also determined using the .slice() method to be the most optimal approach of them all.

In the articles to follow, we will do more array manipulation exercises to strengthen our competence in that area.

Further Reading

For further study of the concepts highlighted above, you may use the following links:

See you in the next one!✌🏿

Like this article? Follow @worldclassdev on Twitter