Map, CompactMap, and FlatMap in Swift
How and when to use them

In a normal app, it is very common to work with arrays. Often we need to take all the elements, one by one and apply some transformations to them.
It happens very often and I see a lot of junior or mid developers carry out this task using a classical iteration, with something like forEach
, not knowing that there are better functions to solve this problem right in the Foundation
framework.
Map
The map is a standard Swift function, used on a collection, that takes in input a closure to apply on every element and returns a different collection. In other words, you have a starting array, you take all the elements of the array one by one, apply on every single one of them a transformation ruled by your closure and append the resulting value on a new array.
Ok, let’s make an example. Let’s say we want to create a game where the player is given the anagrams of the names of Marvel heroes and he/she has to guess the right character. We have a list of names and we have to apply the next steps to every item of the list:
- Transform the names in lowercase
- Remove the whitespaces
- Shuffle the letters
Without map
using a forEach
for example you would need, for each step of course, to create an empty array, apply the step on each element and append the result… three arrays, too much stuff and quite hard to read and understand. Let’s see how verbose is this approach:
Using map
instead everything is extremely easy and readable. It’s just like magic!
As you can see that’s extremely readable even if you don’t know all the steps involved.
CompactMap
CompactMap
works similar to map but with a bonus… it removes every nil
elements given by the transformation.
Let’s see a quick example:
As you can see, an emoticon cannot create a valid url. Using compactMap
you can filter it without any problems or other checks.
CompactMap
is also a great way to filter a list to remove any nil
value. Recently I was working on an app where all the labels of the UI of one view controller were ruled by data sent by the server. If a value was there, you had to show the label, if not the label would be hidden without leaving a blank space.
Everything was dynamic in a UITableView
so I only needed to add an item or not in the datsource (if you are interested in my personal technique to deal with datasources and sections take a look at this article).
Well, filtering everything with compactMap
was super fast and super readable. Something like this, of course in the app was a bit more complicated:
Please note one thing in the latest example. The field array is of type [String?]
while the items array is of type [String]
so the returning type of compactMap
is never an optional
. Wow, amazing!
FlatMap
The last type of map is a function that, as the name says, flattens an array of arrays. It simply transforms a series of arrays into a single one in one pass, something like this:
[[1, 1, 1], [2, 2, 2], [3, 3, 3]] -> [1, 1, 1, 2, 2, 2, 3, 3, 3]
Let’s make an example.
You are coding one of those games with squads of fighting heroes. Your team has a group of characters and you decide who fights in each game.
In every round the number of enemies defeated is added to the stats of the playing hero. You now need to calculate the average number of defeated enemies per round of your squad, so basically you need to create a single array of all the stats of all the heroes and find out the mean value.
Let’s take a look at the code:
All the magic is done at line 25. Please note that I’ve used an extension to calculate the mean value ( line 26 ) instead of the vDSP.mean
function ( link here ) of the Accelerate
framework in order to keep the nice functional programming style.
One More Thing
If you read carefully at the beginning of the article, you may have noticed that I wrote about collections instead of simple arrays. Do you know why? Because the map functions could be applied to dictionaries as well! Any way to use those functions with dictionaries, extra care is needed:
As you can see from the example, the original dictionary is split into an array of dictionaries. Now, you may like to apply a transformation only to the values of the dictionary and not to the keys.
Well, you know what? Swift has a series of maps for all the three previous variants to accomplish this task! Simply use the mapValues
version:
As you can see the result is a [String: String]
and not a [[String: String]]
like the previous example.
I hope you liked this article, if you did please clap it.
If this article was useful to you, feel free to offer me a coffee and and allow me to create more cool contents and articles.
Enjoy your coding!