DEV Community

Cover image for Map, Filter and Reduce in Swift
Eleazar Estrella
Eleazar Estrella

Posted on • Edited on

5 1

Map, Filter and Reduce in Swift

Swift, like many modern languages, has implemented some beautiful, functional capabilities to its core. If you are not experienced with the functional paradigm, it's common to implement the classic for-loop for resolving the frequently seen problems around collection types, but that's not the Swiftiest way. So today, I'm going to introduce High Order Functions, which will let you simplify your code when a collection type joins in.

A Higher-Order Function is a function that receives other functions as arguments or a function that returns another function as its result. We'll be using Map, Reduce, and Filter in this post. Let's get started!

Map

In many programming languages, map is the name of a higher-order function that applies a given function to each element of a functor, e.g. a list, returning a list of results in the same order.
Source: Wikipedia

Instead of writing a for loop and applying your business logic to each element, the map function takes care of that for you. It's only necessary to code the function that will be used to each element, saving us time and lines.

For example:

let array = [1, 2, 3, 4, 5, 6, 8]
//sums 1 to each element
var mappedArray = array.map({
(value: Int) -> Int in
return value + 1
}) //it iterates and applys this closure to every item in the array
//more simplified
mappedArray = array.map { e in
return e+1
}
//even more simplified
mappedArray = array.map { $0 + 1}
// mappedArray-> [2, 3, 4, 5, 6, 7, 9]

Also you are able to transform your collection to another collection with a different type.

let array = [1, 2, 3, 4, 5, 6, 8]
//convert the Array<Int> to Array<String>
var mappedArray = array.map({
(value: Int) -> String in
return String(value)
}) //it iterates and applys this closure to every item in the array
//more simplified
mappedArray = array.map { e in
return String(e)
}
//even more simplified
mappedArray = array.map { String($0) } //return an array of strings
//mappedArray -> ["1", "2", "3", "4", "5", "6", "8"]

Filter

In functional programming, filter is a higher-order function that processes a data structure (usually a list) in some order to produce a new data structure containing exactly those elements of the original data structure for which a given predicate returns the boolean value true.
Source: Wikipedia

The filter function iterates over a collection and then returns a new array containing those elements that have matched our predicate condition.

//returns a new array only with even numbers
var filteredArray = array.filter({
(isIncluded: Int) -> Bool in
return isIncluded%2==0
})
//more simplified
filteredArray = array.filter { e in
return e%2==0
}
//even more simplified
filteredArray = array.filter { $0%2==0 }

Reduce

In functional programming, fold (also termed reduce, accumulate, aggregate, compress, or inject) refers to a family of higher-order functions that analyze a recursive data structure and through use of a given combining operation, recombine the results of recursively processing its constituent parts, building up a return value.
Source: Wikipedia

Okay, that sounds too technical. Let me explain it in other words. What reduce function does is to combine every item of a collection in a unique value.

let array = [1,2,3,4,5,6]
//starting on zero, sum every element to the result
var reducedValue = array.reduce(0) { (result, e) -> Int in
//initially result is zero
return result + e
} //returns 12
//simplified
reducedValue = array.reduce(0, +) //12

Let's see all of these together in action. Do you remember my previous post where I was introducing a new way to solve a common problem? Now let's do that again but using what we just learned.

So, now instead of using the classic for-loop like this:

extension Array where Element == Piece {
var totalPrice: Double {
var x = 0.0
self.forEach { piece in
if piece.selected { x+=piece.price}
}
return x
}
}
let pieces = [Piece]()
let stringArray = [String]()
print(pieces.totalPrice) //prints the total price of selected pieces
print(stringArray.totalPrice) //throws Value of type '[String]' has no member 'totalPrice'

We could just reduce this to a one single line:

extension Array where Element == Piece {
var totalPrice: Double {
//YES, you can combine them
return self.filter { $0.selected }.map { Double($0.totalPrice) }.reduce(0.0, +)
}
}

It's now more elegant than before.

Billboard image

The Next Generation Developer Platform

Coherence is the first Platform-as-a-Service you can control. Unlike "black-box" platforms that are opinionated about the infra you can deploy, Coherence is powered by CNC, the open-source IaC framework, which offers limitless customization.

Learn more

Top comments (0)

A Workflow Copilot. Tailored to You.

Pieces.app image

Our desktop app, with its intelligent copilot, streamlines coding by generating snippets, extracting code from screenshots, and accelerating problem-solving.

Read the docs

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay