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.
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]
.
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 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.
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)