Most high-level languages have some variation of map, reduce and filter and Swift is no different. These functions operate on arrays to turn them into something else that is more useful to you. For example, map is used to iterate over an array and, for each value, return another value derived from it. For example:

let arrayOfNumbers = [3, 12, 5, 2]
let arrayByAddingTwo = arrayOfNumbers.map { (number) -> Int in
    return number + 2
}

// arrayByAddingTwo is now [5, 14, 7, 4]

Okay, so a function that adds two to an array of numbers may not be all that useful, but you can probably see how a function that iterates over an array and transforms it into values in another array can be useful. You probably do something similar all of the time.

“But wait”, you say, “can’t we just do this with a for in loop?” Right you are, astute reader.

let arrayOfNumbers = [3, 12, 5, 2]
var arrayByAddingTwo = Int
for num in arrayOfNumbers {
    arrayByAddingTwo.append(num+2)  
}

// arrayByAddingTwo is now [5, 14, 7, 4]

“See? Why do we need this whole other thing when we can just build an array with an existing control flow structure?”

While it may look like the end result is the same, there is one subtle difference. In the first example, arrayByAddingTwo is immutable, while in the second, it is mutable.

And remember, Swift really likes things to be immutable as much as possible. Now, of course, you could just copy the mutable arrayByAddingTwo into an immutable array, but by that point, we’re making an already longer block of code even longer. Functions like map increase readability by focusing on the task at hand (in this case, adding two to a number) instead of mucking about with boilerplate.

And with Swift’s shortened syntax, we can make this code even shorter:

let arrayOfNumbers = [3, 12, 5, 2]
let arrayByAddingTwo = arrayOfNumbers.map { $0 + 2 }

// arrayByAddingTwo is now [5, 14, 7, 4]

Two lines. Awesome. I mean, is it really necessary to have 5+ lines of code for just adding two to an array? I assert that, no.

The other functions, reduce and filter are used similarly. reduce coalesces an array into a single, immutable, value and filter returns an immutable array with a subset of the given array. I’ll leave those as a research exercise for the reader, because what’s really interesting is flatMap.

Whenever you get a new hammer, everything starts looking like nails, even screws. -The Internet

Yeah, but flatMap is a really good hammer. -Me

So what does flatMap do? It coalesces multi-dimensional arrays into a single dimension.

😐

“That’s it?” you are surely saying. “That’s the magical flatMap.” Sure, when I say it that way, it sounds kind of lame. But this great post by Natasha the Robot points out that is less about coalescing arrays as much as it is about coalescing containers of values. We’ll see why this is a big deal in a moment.

So, let’s take the multi-dimensional array:

let multiDimensional = [[1,2], [3,4], [5, 6]]

It’s a little awkward for what we want. It’d be better if it were just an array of numbers. flatMap can help with that.

let singleDimension = multiDimensional.flatMap { (subArray)
    return subArray
}

flatMap will unwrap those sub-arrays and line up everything in a nice, immutable array of Ints like so:

 // singleDimension is now [1,2,3,4,5,6]

We could have used it like a map as well, transforming the values as they were being unwrapped.

“I mean, yeah, that’s cool and all, but far from magical,” you say.

We’re not done with flatMap yet.

So, lets look at this situation:

let imagesNames = ["image1", "image2", "image3"]
let images = imageNames.map { (imageName) -> UIImage? in
    return UIImage(named:imageName)
}

// images is an array of type UIImage?

This map function transforms our array of image names that reference images in our asset library and returns an array of images…sort of. UIImage(named:) is a fail-able initializer, which means it doesn’t return an UIImage, it returns a UIImage? which may be nil. Now, this may be fine, but we probably want an array of UIImage, which means we’ll have to add a bit more code.

let justImages = images.filter { (image) -> Bool
    return image != nil    // Only returns the UIImages
} as! [UIImage]

Now we’ve filtered out all of the UIImage optionals that are really just nil and we are left with those that really have a UIImage in them. We can then force cast the array to [UIImage] since we know we’ve removed all of the nils.

If that bang makes you a little nervous, it should. It’s not very Swifty and even though we know it’s safe to do what we’ve done, there is a better way.

You guessed it, flatMap. Now it’d seem like flatMap has nothing to do with this situation. This is a single dimension array of optionals, not a multidimensional array, but remember what we said about flatMap working on collections. What is optional, really, but a collection that contains at most one value.

Yep, flatMap can unwrap optionals.

Let’s redo the code from above using flatMap:

let imagesNames = ["image1", "image2", "image3"]
let images = imageNames.flatMap { (imageName) -> UIImage? in
    return UIImage(named:imageName)
}

// images is of type [UIImage]

We just plopped that flatMap and it did the work of unwrapping those optionals, giving us a nice, clean array of UIImages. Magic.

Look around your code. Especially if you deal with JSON data from a web server or data entered by the user, you probably have collections with optionals everywhere. flatMap can help you strip out those optionals and give you clean, immutable typed arrays that are much easier to work with.