In this series on Swift code topics, various features of the Swift programming language are explored with examples of code. I use Xcode playgrounds for learning how Swift code functions since that platform fosters exploration. The code examples used in this post on map and filter functions have been uploaded to GitHub.

Since its introduction to the Apple development platform in 2014 (announced at WWDC 2014), Swift (currently Swift 5.5) continues to mature rapidly due to its open development community (Swift.org). As such, Swift code is cleaner to write, is strongly typed, compiles to a fast executable, and includes many best-in-class design principles.

Function: map(_:)

The map(_:) function applies a transformation on each item in a collection, essentially mapping one set of values to another set of values of possibly a different type. The map function is defined for a collection type (e.g., Dictionary, Set, Array), not just Arrays.

The first basic example squares the value of each integer value:

let numberArray = [1, 2, 3, 4, 5]
let squaredArray = numberArray.map { $0 * $0 }
print(squaredArray) // [1, 4, 9, 16, 25]

The second basic example converts an array of Fahrenheit temperatures to an array of Celsius temperatures:

let fahrenheit = [-40.0, -4.0, 32.0, 98.6, 212.0]
let celsius = fahrenheit.map { ($0 - 32) * 5 / 9 }
print(celsius) // [-40.0, -20.0, 0.0, 37.0, 100.0]

The third basic example converts the array of numbers to an array of strings:

let numbers = [1, 2, 3, 4, 5]
let strings = numbers.map { "\($0)" }
print(strings) // ["1", "2", "3", "4", "5"]

Function: filter(_:)

The filter(_:) function applies a condition to the values of a collection type. Only those values that satisfy the condition are included in the resultant collection type.

The first basic example extracts the values from an array that are modulo 2:

let numbersArray = [10, 11, 12, 13, 14, 15]
let mod2Array = numbersArray.filter { $0 % 2 == 0 }
print(mod2Array) // [10, 12, 14]

The second basic example extracts all occurrences of items in the miniArray from the mainArray:

let mainArray = ["one", "two", "three", "four", "five", "six", "two", "two", "three", "seven", "eight"]
let miniArray = ["two", "three"]
let filteredElements = mainArray.filter( { miniArray.contains($0) } )
filteredElements // ["two", "three", "two", "two", "three"]

Real-life map(_:) and filter(_:) Examples

For the following examples, we have a collection of vintage muscle-cars stored in various garages.
Structs and arrays for the garage and vehicles are defined below. Since vehicles are stored in a garage, the vehicle struct includes a parameter for a garage ID. An order parameter is also included to support persistence in re-ordering the vehicles, by favorites for example.

public struct Garage: Codable, Identifiable, Equatable, Hashable {
    public var id: UUID
    public var garageOwner: String
    init() {
        self.id = UUID.init()
        self.garageOwner = ""
    }
    init(id: UUID, garageOwner: String) {
        self.id = id
        self.garageOwner = garageOwner
    }
    public static var localGarages: [Garage] = [
        Garage(id: UUID(uuidString: "95A0D1D1-491F-46FE-A51B-80FC5B381D76")!, garageOwner: "Cary's Garage"),
        Garage(id: UUID(uuidString: "96A5902E-5408-437C-AF44-16F39DF90C5A")!, garageOwner: "Amy's Master Shop"),
        Garage(id: UUID(uuidString: "F64EB5B1-DE87-46CA-A75A-75D7620A4DCE")!, garageOwner: "Scott's Tech Shop"),
        Garage(id: UUID(uuidString: "46F64638-EAD2-49F0-A0A6-C1AD047B225B")!, garageOwner: "Maureen's Vintage Cars"),
    ]
}
public struct Vehicle: Codable, Identifiable, Equatable, Hashable {
    public var id: UUID
    public var make: String
    public var model: String
    public var year: Int
    public var garageID: UUID
    public var order: Int
    init() {
        self.id = UUID.init()
        self.make = ""
        self.model = ""
        self.year = 2021
        self.garageID = UUID.init()
        self.order = 1000
    }
    init(id: UUID, make: String, model: String, year: Int, garageID: UUID, order: Int) {
        self.id = id
        self.make = make
        self.model = model
        self.year = year
        self.garageID = garageID
        self.order = order
    }
    public static var vehicles: [Vehicle] = [
        Vehicle(id: UUID.init(), make: "Ford", model: "Shelby Mustang GT350", year: 1965, garageID: UUID(uuidString: "95A0D1D1-491F-46FE-A51B-80FC5B381D76")!, order: 5),
        Vehicle(id: UUID.init(), make: "Chevy", model: "Camaro Z/28", year: 1967, garageID: UUID(uuidString: "96A5902E-5408-437C-AF44-16F39DF90C5A")!, order: 2),
        Vehicle(id: UUID.init(), make: "Chevy", model: "Corvette L88", year: 1968, garageID: UUID(uuidString: "95A0D1D1-491F-46FE-A51B-80FC5B381D76")!, order: 0),
        Vehicle(id: UUID.init(), make: "Plymouth", model: "Hemi 'Cuda", year: 1971, garageID: UUID(uuidString: "46F64638-EAD2-49F0-A0A6-C1AD047B225B")!, order: 4),
        Vehicle(id: UUID.init(), make: "Pontiac",  model: "GTO", year: 1964, garageID: UUID(uuidString: "95A0D1D1-491F-46FE-A51B-80FC5B381D76")!, order: 1),
        Vehicle(id: UUID.init(), make: "Ford", model: "Fairlane Thunderbolt", year: 1964, garageID: UUID(uuidString: "46F64638-EAD2-49F0-A0A6-C1AD047B225B")!, order: 3)
    ]
}

Example 1: Determine which garages have my two favorite cars

In this first example, an array contains the model names for my two favorite muscle-cars.

let favVehicleList = [
    "Shelby Mustang GT350",
    "Camaro Z/28"
]

The first line of the following code maps the garageIDs after filtering the vehicles array with the vehicle model names of my two favorite muscle-cars. The second line of code maps the garageOwners after filtering the localGarages array with the garageIDs from the first line of code.

let garageIDwithFavVehicles = Vehicle.vehicles
    .filter( {favVehicleList.contains($0.model) } )
    .map { $0.garageID }
let garageOwners = Garage.localGarages
    .filter( {garageIDwithFavVehicles.contains($0.id) } )
    .map { $0.garageOwner }
// ["Cary's Garage", "Amy's Master Shop"]

Example 2: Determine which of the available garages have vehicles

In this second example, we want an array that lists which garageOwners actually have vehicles stored in their garage. The first line extracts the garageIDs from all the vehicles and removes duplicate garageID entries. The second line of code maps the garageOwners after filtering the localGarages array with the garageIDs from the first line of code.

// Sort Vehicle array retrieved from DB by item order
let sortedVehicles = Vehicle.vehicles
    .sorted { $0.order < $1.order }
// Save index to 'order' for each item in array
let reorderedVehicles = Vehicle.vehicles.enumerated()
    .map { (index, item) -> Vehicle in
        var localVehicle: Vehicle = item
        localVehicle.order = index
        return localVehicle
    }

Example 3: Persist modified array order of vehicles

In this third example, we want to persist any changes to the order of vehicles in the vehicles array. This may occur when a user is re-ordering the vehicles according to some preference (e.g., favorites) from within a SwiftUI List. Saving the array of vehicles to a database does not guarantee that reading the vehicles back from the database will persist order. To persist order, an order variable is used to store the modified index. The first line simulates retrieval of the vehicles array and sorts by order. The second line of code maps the index onto the order variable for each vehicle. Afterwards, the reorderedVehicles array can be written to a database.

// Sort Vehicle array retrieved from DB by item order
let sortedVehicles = Vehicle.vehicles
    .sorted { $0.order < $1.order }
// Save index to 'order' for each item in array
let reorderedVehicles = Vehicle.vehicles.enumerated()
    .map { (index, item) -> Vehicle in
        var localVehicle: Vehicle = item
        localVehicle.order = index
        return localVehicle
    }

Summary

As the examples in this post highlight, clear and concise code can be written in Swift. Swift is truly an amazing modern programming language.

Reference Information:

Map, FlatMap, and CompactMap by John Sundell.

Transforming collections in Swift by John Sundell.

Inside the Standard Library: Sequence.map() by Paul Hudson.

How To: Map, Reduce, and Filter in Swift by Reinder de Vries.

Swift Guide to Map Filter Reduce by Keith Harrison.

Credits

The Xcode logo, Swift, and Swift logo are copyrights and trademarks of Apple.