How to Use Swift Map to Transforms Arrays, Sets, and Dictionaries

How to Use Swift Map to Transforms Arrays, Sets, and Dictionaries

The Swift standard library defines a wide range of useful types, methods, and functions. The map(_:) method is one of them. It is easy to use and powerful. Create a playground in Xcode by choosing the Blank template from the iOS > Playground section. Give the playground a name and click the Create button.

Creating a Playground in Xcode

Use Swift Map to Transform an Array

Replace the contents of the playground with an import statement for Foundation.

import Foundation

The map(_:) method has the ability to transform a sequence of elements. Let me show you what that means. We define a constant, strings, and assign an array of String objects to it. The array of strings contains the elements one, two, and three.

import Foundation

let strings = [
    "one",
    "two",
    "three"
]

We can use the map(_:) method to transform the elements of the array. I would like to create an array that contains the number of characters of each string in the array. We invoke map(_:) on strings and pass a closure to the map(_:) method. The closure is executed for each element of the array and it accepts the element as its only argument.

We need to define what the return type of the closure is, that is, the type of the transformed value. Because we would like to transform the string to the number of characters it contains, the return type of the closure is Int. We ask the String object for the value of its count property, the number of characters it contains. The transformed array is stored in a constant with name ints.

import Foundation

let strings = [
    "one",
    "two",
    "three"
]

let ints = strings.map { (string) -> Int in
    return string.count
}

We can simplify the implementation and make it a bit more elegant. Because the closure contains a single statement, there's no need to use the return keyword.

import Foundation

let strings = [
    "one",
    "two",
    "three"
]

let ints = strings.map { (string) -> Int in
    string.count
}

We can use the shorthand argument name of the element by replacing string with $0. We can also omit the return type of the closure since the compiler can use type inference to infer the return type. The compiler knows that the closure returns a value of type Int so there is no need to specify it explicitly.

import Foundation

let strings = [
    "one",
    "two",
    "three"
]

let ints = strings.map { $0.count }

This looks much better and easier to understand. Print the value of ints to the console and run the contents of the playground. The output in the console should read [3, 3, 5].

Use Swift Map to Transform an Array

Transforming the Values of a Set Using Swift Map

You can also use the map(_:) method to transform the values of a set. This is very similar to mapping the values of an array. The difference is that the order of the elements of the resulting array is undefined because a set doesn't order its elements. Take a look at the example below.

import Foundation

let strings = Set([
    "one",
    "two",
    "three"
])

let ints = strings.map { $0.count }

print(ints)

Run the contents of the playground to see the result. You can verify that the order of the elements is undefined if you run the contents of the playground several times.

Transforming the Values of a Set Using Swift Map

Transforming a Dictionary with Swift Map

It should be no surprise that Swift's map(_:) method can also be used to transform the keys and values of a dictionary. This is a bit odd, though. The key-value pairs are transformed to an array and that isn't a common operation. Let's create a dictionary of type [String:String]. The dictionary contains country codes as keys and country names as values.

import Foundation

let countries = [
    "US": "United States",
    "BE": "Belgium",
    "CN": "China"
]

We can invoke the map(_:) method on the dictionary of country codes and country names. The closure we pass to map(_:) accepts a single argument, a tuple. The tuple contains the key and the value of the element. We can access the key through the key named value and the value through the value named value. We can also use 0 and 1 to access the key and the value respectively.

import Foundation

let countries = [
    "US": "United States",
    "BE": "Belgium",
    "CN": "China"
]

let ints = countries.map { $0.value.count }

print(ints)

In this example, we transform each key-value pair to an integer, that is, the number of characters of the country name. The order of the elements of the resulting array is also undefined because the key-value pairs of a dictionary are unordered.

Transforming a Dictionary with Swift Map

Mapping the Values of a Dictionary In Swift

In the previous example, we used map(_:) to transform a dictionary to an array. This can be useful at times, but it's more common to only transform the values of the dictionary and keep the keys as is. This is possible using the mapValues(_:) method. As the name implies, mapValues(_:) only transforms the values of the dictionary. It returns a dictionary, not an array.

In this example, we invoke mapValues(_:) on the dictionary of country codes and country names. We transform the value of each key-value pair to an integer, the number of characters of the country name. The result of mapValues(_:) is a dictionary of type [String:Int].

import Foundation

let countries = [
    "US": "United States",
    "BE": "Belgium",
    "CN": "China"
]

let ints = countries.mapValues { $0.count }

print(ints)

Mapping the Values of a Dictionary In Swift