What the Map are these functions in Swift?

If you have used functional programming, then you would already have a good understanding of what these map, flatMap, filter, reduce, etc commands are all about. However, if you are still trying to get your head around these and its doing your head in, then you need to read on.


There are a lot of articles that talk about functional programming, map, reduce etc. There are some very nice examples but the point is unless you actually get to use them, you would never know how these work. There are also others that talk of FRP and RAC and Signals, etc. I have also met someone that has made a simple piece of code complicated and so dependent on signals, etc spanning over couple of files. I guess the idea is to make things easy and small/compact while allowing you to do what you want.

MAP-ping your start

Heard of the map command? first things first, it allows you to transform the contents of a variable (Optional or an Array) via a closure or a function. If that did not make much sense, well that's ok.

Let's look at a simple example, we have a structure, called Student that has three properties, name, age and subjects.
struct Student {
    var name: String?
    var age:Int? = 0
    var subjects:[String]? = []

lets now create some data and then an array from that

let jack = Student(name:"Jack", age:18, subjects:["Math", "Chemistry", "Biology"])
let daniel = Student(name:"Daniel", age:19, subjects:["English", "Drama "French", "Music"])

let students = [jack, daniel]

now we have an array called students that contains the student jack and daniel. If you print, you would see 'Student(name...' printed out.

What if you wanted to have an array that contained the name of the Student followed by the number of subjects they are studying. Something like 'Jack, 18 (3)' and 'Daniel, 19 (4)'

traditionally, you would iterate through the array and then print this out or save it to a new array, like so
var resultingArray:[String] = []
for student in students {
    resultingArray.append("\(student.name!), \(student.age!) - (\(student.subjects?.count ?? 0))")

Now that was easy, what if there was an easier way to achieve the same? there is and its called map. The map function allows you to transform the contents of an array to another.

let results = students.map{ "\($0.name!), \($0.age!) - (\($0.subjects?.count ?? 0))" }

The same result in a line. You do not have to use the for loops to iterate through the array. This is a very basic example and the map can be a very powerful tool at your disposal.

your Filter needs changing

This is the second most useful command that is literally under utilized. i.e. not many are aware of this command or use it. All it does is returns elements from an array as an array but by removing the entities that do not match the function / closure. In the same example, say we wanted to remove all students that were under 18, we could simply do this
let jack = Student(name:"Jack", age:18, subjects:["Math", "Chemistry", "Biology"])
let daniel = Student(name:"Daniel", age:19, subjects:["English", "Drama", "French", "Music"])
let scott = Student(name:"Scott", age:16, subjects:["PE", "Computers"])

let students = [jack, daniel, scott]

let studentsOver18 = students.filter{ $0.age > 18 }

this would have been the equivalent to this code
var resultsArray:[Student] = []
for student in students {
    if student.age > 18 {

By altering the condition in the filter command you can have different results, say you wanted to get the students that were attempting more than 3 subjects, you could simple change it as

let studentsFullEFTSL = students.filter{ $0.subjects?.count > 3 }

Other functionality

There are other functionalities that are available with filter, that we will explore in a later article. For now you can try playing with this and see how map and filter can help you iterate through arrays. This can also help you work easier with other data types.


Popular Posts