Explain Codes LogoExplain Codes Logo

Split array into chunks

javascript
promises
callbacks
functional-programming
Anton ShumikhinbyAnton Shumikhin·Sep 4, 2024
TLDR

Here's a succinct solution to your problem: the function creates a new array and uses a loop to extract sub-arrays of the given size from the input array with the slice method:

const chunkArray = (array, size) => Array.from({ length: Math.ceil(array.length / size) }, (_, index) => array.slice(index*size, index*size+size) ); // Example console.log(chunkArray([1, 2, 3, 4, 5], 2)); // Outputs: [[1, 2], [3, 4], [5]]

This one-liner offers a neat solution using Array.from and math to determine the number of chunks.

Advanced strategies for array chunking

Limitations of the brute-force method

The fast answer is a kind of brute-force method. It's pure fire and forget. But it may be inefficient for large arrays or when your chunk size is small.

Exploit ES6 features: reduce and concat

The ES6 reduce method combined with concat provides an elegant functional programming approach:

const chunkArrayWithReduce = (array, size) => array.reduce((toast, butter, index) => index % size ? toast : [...toast, array.slice(index, index + size)], []); // console.log(chunkArrayWithReduce(["eggs", "bacon", "coffee", "toast", "butter"], 2)); // Who ordered the all-American breakfast?

Generators: The lazy way is the efficient way

For large arrays, a generator function is more suitable as it yields chunks without creating an bulky intermediate array. Because less is more!

function* chunkArrayGenerator(array, size) { for (let i = 0; i < array.length; i += size) { yield array.slice(i, i + size); } // choco = chunkArrayGenerator(["☕","🍩","🍩","🍩","☕","🍩","🍩","🍩","☕"], 3); // Who wants a coffee with three donuts? }

Enter TypeScript stage right

For bonus points and a crisp high-five from your compiler, use TypeScript for reliable type safety:

function* chunkArrayGenerator<T>(array: T[], size: number): Generator<T[]> { for (let i = 0; i < array.length; i += size) { yield array.slice(i, i + size); } }

Caveats and guidelines for usage

Zero-size chunks: Cue endless loop

Ensure that chunkSize is not zero unless you've stocked up for the winter and are ready for an infinite coding session:

if (size <= 0) { throw new Error('Size must be positive, or you enter "Groundhog Day" mode'); }

No uncontrolled magic

Your chunking function should behave predictably, a la Principle of Least Surprise. Remember, a magician never reveals their secrets, but your code should.

Keep it local

Confine chunk functions within local modules to avoid an outbreak of naming conflicts in the global namespace. Keep the global namespace clean and green!

Array chunking and performance

All chunking methods described have the same running time, however, not all are created equal when it comes to constant factors. Those avoiding intermediate structures are secretly doing pilates and hence can boast of better constant factor efficiency.

Additional areas to explore

Diverse uses of map and fill

The Array.map and Array.fill offer another dynamic duo for an expressive solution:

const chunkArrayWithFill = (array, size) => Array.from({ length: Math.ceil(array.length / size) }) .fill() .map((_, index) => array.slice(index * size, (index + 1) * size));

Iteration methods: The art of going through your array

Simple iteration methods such as forEach and for...of can also craft chunks, but they lack the superhero cape that Array.from and reduce wear.

DIY chunk method

You might be itching to add a custom method to the Array prototype. Simmer down, cowboy. This reeks of potential issues, especially in larger code projects.

Edge cases: Come to the edge, they said

Edge cases are like unexpectedly stepping on a Lego brick. Make sure your function can handle situations where the array cannot be evenly split.