Using the JavaScript array method flatMap()
Tags: javascript, webdev, beginners, tutorial
Published: 2022-02-24 20:25:24

INTRODUCTION - flatMap()

This tutorial will demonstrate how to use the map(), flat() and flatMap() array methods in JavaScript.  flatMap() is a newer array method which was introduced in es2019.  As described by MDN web docs __flatMap can be used as a way to **add and remove items (modify the number of items) during a map.** In other words, it allows you to map many items to many items (by handling each input item separately), rather than always one-to-one. In this sense, it works like the opposite of filter.__ In simple 
terms, this method gives you the ability to map, but also to remove or even add new items in the resulting mapped array.  The same results of flatMap() can be achieved by using a map() followed by a flat() but using flat map is more efficient and provides for cleaner code.


REFRESH - How flat() works

The flat() method creates a new array with all sub-array elements concatenated into it recursively up to the specified depth.  Let's look at an example of using the flat method.

```javascript
const numberArray = [
1,2,[3,4,5],6,[[7,8],[8,9],[10,11,12]],13,[[14,15],[16,17]],[18]
];
 
```
Using the flat() method on the above numberArray will create a new array by removing the nested arrays at a specified depth. The default depth is one level.

```javascript
let flatArray = numberArray.flat();
console.log(flatArray);
```
Running this code will provide the following **RESULT =>**

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6sgp4023noh9hwp70tnm.png)

As you can see, we now have an array that no longer has nested arrays.  There are however elements within the new array that are still arrays.  These can be removed if we had run the flat() method at a depth of 2.  See below.

```javascript
let flatArray = numberArray.flat(2);
console.log(flatArray)
```

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0afo1ahsiriy82tkidfl.png)

We now have a flat array where each element is an individual number from the numbersArray!

REFRESH - How map() works

The map() method creates a new array from calling a function on every array element in the array that's called.  There are a few important things to note about the map() method:

- map() does not execute the function for an empty element.
- map() does not change the original array.

Map is similar to forEach() however forEach() does not return anything and is affecting the original array. map() provides a new array built out of all the return values.

Here is an example of using the map() method:

```javascript
let skiResorts = [
  "Meadows",
  "Crystal",
  "Big Sky",
  "Kicking Horse",
  "Jackson Hole",
  "Alta",
  "Park City",
  "Crested Butte",
  "Aspen"
];

let nameLengths = skiResorts.map(function (item, index, array) {
   return item.length;
});

console.log(nameLengths);
```
In this example the map() method is being used to create an array of the length of each string within the skiResorts array.  Here are the **RESULTS =>**

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yvlwmnpwxemqj6n0c83j.png)

USING THE flatMap() METHOD

The following example will demonstrate how flatMap() can be a useful tool to non-destructively transform messy data into a usable format. Check out the following skiResorts array.

```javascript
let skiResorts = [
  "Meadows",
  ["Crystal", "Stevens Pass"],
  "",
  "    ",
  "Park City,Deer Valley,  Canyons,  ",
  "Crested Butte, Aspen, A Basin",
  "Revelstoke",
  ["Kicking Horse", "Fernie", "Lake Louise"]
];
```
A couple of things to notice:
-It is an array of ski resort names
-There are entries that are arrays of resort names
-There are empty entries
-There are entries that have a string of resort names separated by commas
-Spacing is inconsistent

The following steps will show how to compress this list where every entry in the array is a single ski resort.

**Step 1**

```javascript
let resortsArr = skiResorts.flatMap((entry) => {
  if (Array.isArray(entry)) return entry;
});

console.log(resortsArr);
```
In this function entry represents each line in the skiResorts array. The if statement is checking to see if each entry is an array and if true then return the array.  Here are what the **RESULTS** look like=>

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dcm696f2pcyzyand836y.png)

Notice that the entries within the skiResorts array that are not arrays are returned with undefined.

**Step 2**

This step will deal with the empty string entries by  adding an else if condition to the conditional.

```javascript
let resortsArr = skiResorts.flatMap((entry) => {
  if (Array.isArray(entry)) {
    return entry;
  } else if (typeof entry === "string" && entry.trim() === "") {
    return [];
  }
});
```
Here the function is checking to see if each entry is both a string and empty, if true it will return an empty array. The reason to return an empty array is to allow for the removal of the empty arrays. Remember that this function is performing a map and then a flat.  The map will return the same number of entries as the original array and then the flat will do a filtering and remove the empty arrays.  Check out the **RESULTS =>**

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/l9yul09hls1z42nr6vac.png)

**Step 3**

Tie to deal with the strings

```javascript
let resortsArr = skiResorts.flatMap((entry) => {
  if (Array.isArray(entry)) {
    return entry;
  } else if (typeof entry === "string" && entry.trim() === "") {
    return [];
  } else {
    return entry.split(",");
  }
});

console.log(resortsArr);
```
A final conditional has been added to the above function. entry.split will return the strings that have multiple resort names and turn them into arrays.  See the **RESULTS =>**

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mstjqk3xs4cwctcfr7w3.png)

This is close to our desired results however there are still some extra spaces that need to be taken care of.

**Step 4**

This is the final step.  Take a look at what has been added to the resortArr function.

```javascript
let resortsArr = skiResorts.flatMap((entry) => {
  if (Array.isArray(entry)) {
    return entry;
  } else if (typeof entry === "string" && entry.trim() === "") {
    return [];
  } else {
    return entry.split(",").map((txt) => txt.trim());
  }
});

console.log(resortsArr);
```

Here a map has been added that uses the .trim() method to remove all the extra spaces in any of the entries within the array. Look at what the resortsArr looks like now.  **RESULTS =>**


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xullau4a4snv3ff7ofwl.png)

resortsArr is now an array where every entry is a single ski resort name (string).

CONCLUSION

flatMap() can be a very useful tool to efficiently and elegantly clean up data in a non-destructive manner.