Implement custom filter and reduce in Swift

App Developer
6 min readDec 21, 2022

--

This article revolves around the second part of higher order functions which is filter and reduce. By the end of this article you will come to know what exactly is the meaning of both and how to develop your own custom filter and reduce.

https://youtu.be/UwwPW_-K5vc

Talking about the formal and official documentation of filter then it “returns an array containing, in order, the elements of the sequence that satisfy the given predicate”. In simpler terms, with the help of filter we can provide a particular condition and satisfying that condition result is returned in the form of an array.

Declaration:

func filter(_ isIncluded: (Self.Element) throws -> Bool) rethrows -> (Self.Element )

Time Complexity :

O(N), N is the length of the sequence

Talking about one of the parameters which is isIncluded , it is the closure that takes an element of that particular sequence as argument and finally returns a boolean value which decides whether the element should be appended or not.

Let’s try to see the implementation of filter. Let’s say if we have an array as the following

let persons = [
Person(name: "Nilesh", isSubscribed: false, email: "a@b.com"),
Person(name: "Ramesh", isSubscribed: true, email: "b@b.com"),
Person(name: "Somesh", isSubscribed: false, email: "c@b.com"),
Person(name: "Somesh", isSubscribed: false, email: "d@b.com"),
Person(name: "Somesh", isSubscribed: false, email: "e@b.com"),
]

In the above array persons we want to filter out(i.e select) those persons whose name is Somesh.

Then we can do it easily with the help of filter like the following.

let persons = [
Person(name: "Nilesh", isSubscribed: false, email: "a@b.com"),
Person(name: "Ramesh", isSubscribed: true, email: "b@b.com"),
Person(name: "Somesh", isSubscribed: false, email: "c@b.com"),
Person(name: "Somesh", isSubscribed: false, email: "d@b.com"),
Person(name: "Somesh", isSubscribed: false, email: "e@b.com"),
]
let filteredArray = person.filter {$0.name == "Somesh"}
print(filteredArray)

So here the compiler will match the condition for each element and for the first element came with name as Nilesh then the condition will be checked as $0.name == “Somesh” and will be false and therefore that element won’t be appended to the resulting array and likewise all the elements will be checked and those element which will satisfy the condition(i.e here whose name will be Somesh) will be returned as true thereby adding it to the resulting array filteredArray.

Output:

Now let’s say if we wanted to filter the array and in response we wanted to get only the email of those filtered elements then that we can do using filter and map. The way it will work is using a filter. We will filter out those elements whose name is Somesh and then with the help of a map we can get only the key as email. Following is the implementation of the same:

let persons = [
Person(name: "Nilesh", isSubscribed: false, email: "a@b.com"),
Person(name: "Ramesh", isSubscribed: true, email: "b@b.com"),
Person(name: "Somesh", isSubscribed: false, email: "c@b.com"),
Person(name: "Somesh", isSubscribed: false, email: "d@b.com"),
Person(name: "Somesh", isSubscribed: false, email: "e@b.com"),
]
let filteredArray = person.filter {$0.name == "Somesh"}.map {$0.email}
print(filteredArray)

Output:

From the above we can grab one important point that we can combine more than one higher order functions in order to perform complex tasks in a single line.

Now let’s see how exactly we can code our own custom filter when let’s say the default filter was not available.

In the above code snippet we can see that we have written the whole code inside extension Collection then we declared a function called myFilter which has first variable as isinclude which has type Element which throws boolean and then it rethrows an array of element which we have written as [Element]. Now coming to the body of the function then what exactly we are doing with the filter function is that we are basically comparing based on the condition provided so firstly in line number 5 we have declared an array results of type Element that will be returned and which contains the resulting array. Then in line 7 we started a for loop which will iterate to self and then inside the loop we are checking if isinclude satisfies or not if it satisfies then we are allowing it to enter and thereby adding it to the resulting array results. Finally in line 12 we are returning the resulting array results.

Now let’s apply our custom myFilter in the following manner

let persons = [
Person(name: "Nilesh", isSubscribed: false, email: "a@b.com"),
Person(name: "Ramesh", isSubscribed: true, email: "b@b.com"),
Person(name: "Somesh", isSubscribed: false, email: "c@b.com"),
Person(name: "Somesh", isSubscribed: false, email: "d@b.com"),
Person(name: "Somesh", isSubscribed: false, email: "e@b.com"),
]
extension Collection{
func myFilter( _ isinclude: (Element) throws -> Bool) rethrows->
[Element]{
var results = [Element]()
for val in self{
if try isinclude(val){
results.append(val)
}
}
return results
}
}
let filteredArray = persons.myFilter {$0.name == "Somesh"}
print(filteredArray)

Output:

Now moving to our second important higher order function which is reduce. So as per the official documentation reduce

“returns the result of combining the elements of the sequence using the given closure” . Major difference between reduce and other higher order functions like map, compactMap, and filter is that a reduce returns a particular value whereas others return an array.

Declaration:

func reduce<Result>(
_ initialResult: Result,
_ nextPartialResult: (Result, Self.Element) throws ->Result
) rethrows -> Result

The first parameter which is initialResult, it’s the initial value. Let’s say the initial value is 0 and the next value is 1 then the next value will be 1. It denotes the value to use as initial accumulating value. Then the nextPartialResult is basically the result that we are calculating with the next value.

Time Complexity :

O(N), N is the length of the sequence

Let’s consider the following piece of code

let numbers = [1,2,3,4]
let sum = numbers.reduce(0) { $0 +$1 }
print(sum)

Output:

In the above code the initial value we have provided is 0 and inside the function we are providing $0 which represents the preceding element and $1 which represents the next element to it.

Now finally let’s move to making our custom reduce. So following is the code depicting the same:

From the above code snippet we can see that at line number 2 we have created our function named myReduce which is nothing but the default declaration way of reduce function. Now in line number 7 we declared a variable result which will contain the result and which will be returned. Moving to line number 8 then we have started our loop to iterate into the array then in line number 9 we called nextPartialResult which will help us calculate the previous value with the next value. And finally in line number 11 we are returning the result thereby giving the same following output:

This wraps our article on filter and reduce.

Enjoying!! I will be adding more post like this. Follow me so that you don’t miss any of them.

If you enjoyed reading this post, please share and give some claps so others can find it 👏👏👏👏👏 !!!!

You can follow me on medium for fresh articles. Also, subscribe me on youtube . It takes little effort from you to subscribe , but it gives me as a content writer some revenue and more motivation to make more content for you. So its my kind request to support me.

If you have any comment, question, or recommendation, feel free to post them in the comment section below!.

--

--