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.
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.
let flatArray = numberArray.flat();
console.log(flatArray);
Running this code will provide the following RESULT =>
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.
let flatArray = numberArray.flat(2);
console.log(flatArray)
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:
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 =>
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.
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
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=>
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.
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 =>
Step 3
Tie to deal with the strings
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 =>
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.
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 =>
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.
Top comments (0)