.flat() Method

I'm back with my first array method post in a long time! I can't believe it's been over a year since I've done one of these. I'm looking at array.flat() today. This is a method that can be used to flatten nested arrays into a single array. It accepts one optional argument, depth, the numeric value to which you want your provided array to be flattened. If depth is not provided, it defaults to 1. This method returns the flattened array as a new array.

No Depth

Let's take a look at a basic example with one level of nesting:

const arr = [1, 2, 3, 4, 5, [6, 7, 8, 9, 10]];

const flattened = arr.flat();
console.log(flattened);
// expected output: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

The provided arr array only has one nested array, or a depth of 1. Because arr.flat() isn't given a depth argument, it defaults to a depth of 1. The new flattened array that is returned is simply [1, 2, 3, 4, 5, 6, 7, 8, 9, 10].

Now let's take a look with one more nested level.

const arr = [1, 2, 3, 4, 5, [6, 7, 8, [9, 10]]];

const flattened = arr.flat();
console.log(flattened);
// expected output: [1, 2, 3, 4, 5, 6, 7, 8, [9, 10]]

Again, because we didn't give arr.flat() a depth argument, it defaults to 1, but the provided arr array has two levels of nested arrays. The .flat() method will only flatten the first level and return flattened as [1, 2, 3, 4, 5, 6, 7, 8, [9, 10]].

Setting a Depth

Let's look at the same two-level-nested array, but pass in a depth to the method.

const arr = [1, 2, 3, 4, 5, [6, 7, 8, [9, 10]]];

const flattened = arr.flat(2);
console.log(flattened);
// expected output: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

Now we're getting that nice, fully flattened array we want. This kind of behavior continues all the way up, no matter how deep the nesting goes or where in the array the nesting occurs. Here's more deeply nested array in the middle of the inputed array:

const arr = [1, 2, [3, 4, [5, [6, [7, 8]]], 9, 10], 11];
const flattened = arr.flat(3);
console.log(flattened);
// expected output: [1, 2, 3, 4, 5, 6, [7, 8], 9, 10, 11]

Infinite Depth

So far we've seen that you have to specify the depth to which you want to flatten your provided nested data. These have been positive numbers passed in as the depth argument. As a side note, if you pass in 0 or a negative number, no flattening happens.

The problem with this is that you would need to know the depth of the data that you're getting. When you're working with new data sources or an API you're not familiar with, you may not be clued into that kind of information. So what do you do if you don't know how deeply the arrays are nested, but you do know that you want a true, flattened array back? You just pass Infinity as the depth.

const arr = [1, 2, [3, 4, [5, [6, [7, 8]]], 9, 10], 11];
const flattened = arr.flat(Infinity);
console.log(flattened);
// expected output: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]

Missing Values

The last behavior I want to call out about this method is how it treats empty or missing values from the provided input array. The method simply removes those empty slots, returning a contiguous, flattened array:

const arr = [1, , [3, , [5, [, [7, ]]], 9, ], 11];
const flattened = arr.flat(Infinity);
console.log(flattened);
// expected output: [1, 3, 5, 7, 9, 11]

It's worth noting that this only applies to empty array elements. null values will still show up in the returned, flattened array:

const arr = [1, , [3, null, [5, [, [7, null]]], 9, ], 11];
const flattened = arr.flat(Infinity);
console.log(flattened);
// expected output: [1, 3, null, 5, 7, null, 9, 11]

Eloquent JavaScript Array Flattening Exercise

If you've followed this blog for the last few years then you may remember a couple of times that I visited the array flattening exercise from Marijn Haverbeke's Eloquent JavaScript.

Use the reduce method in combination with the concat method to "flatten" an array of arrays into a single array that has all the elements of the input arrays.

Here was a solution using the .reduce() Method:

const arrayOfArrays = [[1, 2], [3, 4], [5, 6]];
const flattened = arrayOfArrays.reduce((flat, currentElement) => flat.concat(currentElement), []);
console.log(flattened);
// expected result: [1, 2, 3, 4, 5, 6];

And here was a solution using Array Spread:

const arrayOfArrays = [[1, 2], [3, 4], [5, 6]];
const flattened = [].concat(...arrayOfArrays);
console.log(flattened);
// expected result: [1, 2, 3, 4, 5, 6]

I know the exercise in the book specifically mentions using a reducer, and that the book came out before the .flat() method was available in the language spec, but just for the sake of completion, here is the solution using .flat():

const arrayOfArrays = [[1, 2], [3, 4], [5, 6]];
const flattened = arrayOfArrays.flat(Infinity);
console.log(flattened);
// expected result: [1, 2, 3, 4, 5, 6]

From MDN: "The .flat() method creates a new array with all sub-array elements concatenated into it recursively up to the specified depth."

See more examples and further documentation here.