I’ve come across the flatMap function several times. I’ve used map many times, but didn’t understand why there was a need for flatMap? The function’s description is quite concise and doesn’t explain much (transform is the only closure parameter that this function accepts):

Return an Array containing the concatenated results of mapping transform over self.

“Flat” Array Link to heading

The simplest and most obvious application of flatMap is to reduce the dimensionality of an array:

let array = [[0, 1, 2], [3, 4, 5]]
let flatArray = array.flatMap { $0 } // [0, 1, 2, 3, 4, 5]

Here we don’t change the array’s values. What if we need to get values ten times larger? The first implementation that comes to mind doesn’t work:

let flatArray10 = array.flatMap { $0 * 10 }

The issue is that the argument in the closure taken by flatMap is not a number but an array, i.e., [0, 1, 2], [3, 4, 5]. Therefore, you can get an array of numbers multiplied by 10 in this way:

let flatArray10 = array.flatMap { $0.map { $0 * 10 } }

Optional Link to heading

This function can work not only with arrays but also with optionals. For example, there is an array of numbers in string representation. This can be obtained, for example, in JSON, where numbers were placed in strings. You need to get an array of numbers so that you can work with them as with numbers, not strings. Int has init?() that takes a string and returns a number. The only problem is that it creates Int?, which is not very convenient. This is where flatMap can help. As an example, one of the strings is not a number, and its conversion result to Int will be nil:

let arrayOfStrings = ["0", "1", "a", "2"]
let arrayOfInts = arrayOfStrings.flatMap { Int($0) }
arrayOfInts // [0, 1, 2]

Another good example of such a technique can be creating an array [UIImage] from string image names [String]:

arrayOfImageNames.flatMap { UIImage(named: $0) }

You can also apply flatMap directly to an optional. For example, creating a URL from a string, which is of type String?. It can’t be passed directly. And here flatMap comes to the rescue:

let urlString: String? = "http://apple.com"
let url: URL? = urlString.flatMap { URL(string: $0) }

References: Link to heading