It’s simple! as you already know , .filter is a Higher Order Function for collections in Swift. Just like .map, .filter is also referred as Instance Method .
Why do we need .filter?
.filter :
Well, well … as developer.apple.com says, .filter’s job is to :
Return an array containing, in order, the elements of the sequence that satisfy the given predicate.
I know that it’s somehow hard to understand to make it a little bit readable , we can say that :
.filter returns a new array , with elements which are ok with the predicate (~given logic) declared by the closure; Keep in mind that returned array has the same order as the given array.
Behind the scenes , .filter is doing a simple job; It iterates through the whole given array , checks if the given predicate -passed as a closure- applies to the element , returns a Bool indicating the true/false state of the operation for the element; if it the result were true the element would be added to the array we’re expecting in return .
The only thing we need to know for our daily use is that we can filter an array with .filter by any logic we need and get a new array filtered as we desire !
Here is the example for .filter :
import Foundation
var array = [10, 7, 1, 4, 0, -2, 20]
let newArray = array.filter { (element) -> Bool in
element < 5
}
print(newArray)
let newArraySwifty = array.filter( { $0 < 5 })
print(newArraySwifty)
Can you guess the result ? -> [1, 4, 0, -2]
The passed predicate (logic) was to filter our array to have a newArray with only greater than 3 Integers. Wasn’t it really simple? the complexity in O(n) , as obvious as it is, because it needs to traverse the whole array once to check the given predicate . Note that here , n is the length -count- of main array.
.filter or .compactMap , that is the question!
Think about the following code :
import Foundation
var array = [10, 7, 1, 4, 0, -2, 20]
let newArray = array.filter { (element) -> Bool in
element < 5
}
let newArray_compactMap = array.compactMap { (element) -> Int? in
if element < 5 {
return element
} else { return nil }
}
print(newArray)
print(newArray_compactMap)
let newArraySwifty = array.filter( { $0 < 5 })
let newArraySwifty_compactMap: [Int] = array.compactMap( {
if $0 < 5 {
return $0
} else { return nil }
})
print(newArray)
print(newArray_compactMap)
// Result -> [1, 4, 0, -2]
It seems that we can achieve our goal by writing few more codes with .compactMap instead of .filter ! So , why did Apple bother creating .filter? It’s the tricky part :)
According to developer.apple.com/.filter and developer.apple.com/ .compactMap while .filter’s complexity is O(n) , it is O(m + n) in .compactMap !
The same issues -as .compactMap- go with .map plus .map isn’t able to discard nil resulted elements =)
Here’s where Hamlet comes in and says “To be, or not to be, that is the question: Whether ‘tis nobler in the mind to suffer The slings and arrows of outrageous fortune," … well , I guess by [The slings and arrows] , he meant misusing .compactMap instead of .filter which will cause us so much pain -I’ll assure you it’s nothing near noble =))) .
Next : Part (IV) : What is .reduce in Swift?
*Thanks a lot for coming this far and reading the article :) As you may know it’s a series about Higher Order Functions of Swift’s Collection , so make sure to read next articles as well as previous one -if you hadn’t already- to completely master this subject . Stay Safe , Code Well & Read Macbeth =) *
If you have any questions, suggestions or etc. feel free to contact me at alireza@swiftycode.com . We can also chat about One Piece & Macbeth beside Swift -kidding- on Twitter at @swiftycode_com .