DEV Community

smilesforgood
smilesforgood

Posted on

Dynamically Create an Array of Arrays

The Reason

In a recent algorithm challenge, I wanted to create an iterable collection of ten "buckets" for grouping data. In practice, this meant creating an array of arrays like:

[[], [], [], [], [], [], [], [], [], []]
Enter fullscreen mode Exit fullscreen mode

What Did Not Work

Rather than hard code each set of arrays, I wanted to create this dynamically. My first attempt (from memory and a cursory skim of the MDN docs), was to use the Array constructor with the .fill method chained on:

const arr = new Array(10).fill([]);
console.log(arr);
// => [[], [], [], [], [], [], [], [], [], []];
Enter fullscreen mode Exit fullscreen mode

At first glance, this seemed to work. Console logging my new arr revealed an array containing 10 empty arrays, so I continued solving the algorithm.

As soon as I began populating the inner arrays (the buckets), I noticed that there was an issue - adding an element to one "bucket", for example at index 5, updated EVERY bucket to match, rather than only the intended bucket:

arr[5].push("hello");
console.log(arr);
// => [["hello"], ["hello"], ["hello"], ["hello"], ["hello"], ["hello"], ["hello"], ["hello"], ["hello"], ["hello"]];
Enter fullscreen mode Exit fullscreen mode

Returning to the MDN docs for Array.prototype.fill, the issue became clear:

Screenshot of MDN docs for fill method

As arrays are a type of object, each of my array buckets were actually referencing the same object in memory. So rather than creating 10 distinct arrays, my array was merely displaying 10 copies of the same array.

Array.from to the Rescue

To dynamically create an array of arrays (or other objects), you can instead use the .from method:

const newArr = Array.from({ length: 10 }, () => []);
console.log(newArr);
// => [[], [], [], [], [], [], [], [], [], []];
Enter fullscreen mode Exit fullscreen mode

Per MDN, Array.from accepts an iterable or "array-like" object as it's first argument, and an optional callback function ("mapFn") for a second argument.

Here, {length: 10} is an "array-like" object which will provide the length of the array being created.

The second argument () => [] is the "mapFn", which is called for each element and whose return value is used to populate the array.

Now, pushing an element to the array at index 5, updates only that array, as expected:

newArr[5].push("hello");
console.log(newArr);
// => [[], [], [], [], [], ["hello"], [], [], [], []];
Enter fullscreen mode Exit fullscreen mode

Top comments (1)

Collapse
 
scotttesler profile image
Scott Tesler

Interesting 🤯 Thanks for the explanation and concise solution!