# David Tang

Software Engineer · Teacher · Author · Vegan

# Flattening Arrays in JavaScript with flat() and flatMap()

Last reviewed on March 9, 2019

As of ES2019, there are two new methods on arrays: `Array.prototype.flat()` and `Array.prototype.flatMap()`.

## The `Array.prototype.flat()` Method

The `flat()` method can flatten a multidimensional array. For example:

``````[[1, 2], [3, 4, 5], ].flat();
// [1, 2, 3, 4, 5, 6]
``````

By default, `flat()` will only go one level deep. You can flatten more than 1 level deep by passing a depth argument to `flat()`:

``````[[1, 2], [3, [4, 5]], ].flat(2);
// [1, 2, 3, 4, 5, 6]
``````

Here, the depth of this array is 2 since the array at index 1 contains the array `[4, 5]`.

## The `Array.prototype.flatMap()` Method

The `flatMap()` method is like calling `map()` followed by calling `flat(1)`. For example:

``````['Hello', 'World'].flatMap(word => word.split(''));
// ['H', 'e', 'l', 'l', 'o', 'W', 'o', 'r', 'l', 'd']
``````

If we were to first call `map` on this array, this is what we’d get:

``````['Hello', 'World'].map(word => word.split(''));
// [['H', 'e', 'l', 'l', 'o'], ['W', 'o', 'r', 'l', 'd']]
``````

Then, if we call `flat(1)` on this resulting array, we’d get the same result as when we called `flatMap()`:

``````[['H', 'e', 'l', 'l', 'o'], ['W', 'o', 'r', 'l', 'd']].flat(1);
// ['H', 'e', 'l', 'l', 'o', 'W', 'o', 'r', 'l', 'd']
``````

So, `flatMap()` is like calling `map` followed by `flat(1)`.

## Writing Your Own `flatMap()` Function

Prior to the addition of `flatMap()` to JavaScript, I had a `flatMap()` utility function in one of my projects. The following was my implementation:

``````function flatMap(array, callback) {
return array.reduce((accumulator, item) => {
return accumulator.concat(callback(item));
}, []);
}
``````

And you could use it as such:

``````flatMap(['Hello', 'World'], word => word.split(''));
// ['H', 'e', 'l', 'l', 'o', 'W', 'o', 'r', 'l', 'd']
``````

You could also use `flatMap()` in Lodash, which I imagine is more robust and faster.

## A Practical Example of `flatMap()`

One situation I have found `flatMap()` to be useful is when dealing with time series data. For example, imagine you get the following JSON from an API:

``````[
{
"timestamp": "2019-01-15",
"purchases": [
{"product": "Product 1", "total": 20, "time": "09:00"},
{"product": "Product 1", "total": 60, "time": "12:00"}
]
},
{
"timestamp": "2019-01-16",
"purchases": [
{"product": "Product 1", "total": 40, "time": "10:00"},
{"product": "Product 2", "total": 30, "time": "11:00"}
]
},
{
"timestamp": "2019-01-17",
"purchases": [
{"product": "Product 1", "total": 10, "time": "14:00"},
{"product": "Product 2", "total": 20, "time": "17:00"}
]
}
]
``````

If I wanted to plot this data on a chart, I might need to collect the `total` for each respective product into a single array, depending on the charting library. I could do that with `flatMap()`!

``````let product1Sales = json.flatMap(({ purchases }) => {
return purchases
.filter(sale => sale.product === 'Product 1')
.map(sale => sale.total);
});

// [20, 60, 40, 10]
``````

Disclaimer: Any viewpoints and opinions expressed in this article are those of David Tang and do not reflect those of my employer or any of my colleagues.