Instantly share code, notes, and snippets.

# SheldonWangRJT/Map, FlatMap (CompactMap), Reduce, Filter & Sort.md

Last active March 21, 2022 20:04
Show Gist options
• Save SheldonWangRJT/791c85749051cf4b63b1590f08143156 to your computer and use it in GitHub Desktop.
Swift Map, FlatMap (CompactMap), Reduce, Filter & Sort

# High Order Functions in iOS Swift

It is exaggerating to say we don't need to use `for` loop or `while` loop any more but we can take advantage of the Swift language built in functions to do loops. If I give you a question now. Q: Assuming we have an optional nested array, please calculate the production of the values that are less than 5. `let numbers: [[Int]?] = [[1, 3], nil, [2], [5, 10], nil, [4]]`, what is your best approach to do it?

And you know the solution that I am talking about is following Swift functions:

1. Map
2. FlatMap / CompactMap
3. Reduce
4. Filter
5. Sort

Above functions are all useful for collections (array / dictionary pairs). The only reason I want to mention this is that compactMap is coming maybe in Swift 4.1 or 4.2 to replace flatMap, I just want to maybe give you a bit summary at the same time for all of them. Assuming we will be having an array, and I will give examples of the use of those functions.

## Map

Map is just pretty much equal to `for number in numbers `

```let numbers: [Int]() = [2, 4, 1, 3]
_ = numbers.map { String(\$0) }         // ["2", "4", "1", "3"]```

NOTE: \$0 means each element in the collection

## FlatMap

FlatMap can do what ever Map can do while it has two more functions, filter nil & flatten nested array.

#### Filter Nil

```let optionalNumbers: [Int?] = [2, nil, 3]
let numbers: [Int] = optionalNumbers.flatMap { \$0 }      // [2, 3]```

#### Flatten Nested Array

```let nestedNumbers: [[Int]] = [[2, 4], [3]]
let numbers: [Int] = nestedNumbers.flatMap { \$0 }        // [2, 4, 3]```

#### Optional Nested Array

FlatMap can do one thing at a time, in this case, you need two FlatMaps

```let optionalNestedArray: [[Int]?] = [[2], nil, [4, 3]]
let numbers: [Int] = optionalNestedArray.flatMap{ \$0 }.flatMap{ \$0 }    // [2, 4, 3]```

`compactMap` is actually just a naming changes, because `flatMap` has worse performance than Map, and it can do what map can do. Therefore, Apple tries to clarify the naming to make only use `flatMap`/`compactMap` when it is really needed.

## Reduce

Reduce is to take all elements for calculations
`let numbers: [Int] = [2, 4, 1, 3]`

#### Sum

```let sum = numbers.reduce(0, +)      // 2+4+1+3 = 10
let sum = numbers.reduce(0, { \$0 + \$1 })    // 10```

NOTE: `0` is the initial value we need to consider, for sum, 0 is what we need
NOTE: `\$0` is current number, \$1 is next number in the array

#### Multiply

```let product = numbers.reduce(1, *)      // 2*4*1*3 = 24
let product = numbers.reduce(1, { \$0 * \$1 })    // 24```

NOTE: `1` will be the needed initial value for production
Obviously, you can do other calculations if you want.

## Filter

Filter is my favorite, using Filter, we can find all targeted value.

```let numbers: [Int] = [1, 2, 3, 5]
let bigNumbers = numbers.filter { \$0 >= 3 } // [3, 5]
let biggerNumbers = numbers.filter { \$0 >= 5 } // [5]```

NOTE: the filtered numbers are returning an Array!

## Sort

Sort is pretty common used, as we can easily to ascending or descending orders

```let numbers: [Int] = [2, 3, 1]
let ascdNumbers  = numbers.sorted()     // [1, 2, 3]
let ascdNumbers  = numbers.sorted(by: { \$0 < \$1 })     // [1, 2, 3]
let dsNumbers = numbers.sorted(by: { \$0 > \$1 })    // [3, 2, 1]```

## Final Challenge: A combination of all

Here I will give you a question and you will solve it in peace. Q: Assuming we have an optional nested array, please calculate the production of the values that are less than 5. `let numbers: [[Int]?] = [[1, 3], nil, [2], [5, 10], nil, [4]]`

A: Result will be easily calculated as:

```let result: Int = numbers
.flatMap({\$0})
.flatMap({\$0})
.filter({ \$0 <= 5 })
.reduce(1, *)```

If u will, you can replace flatMap will compactMap as:

```let result: Int = numbers
.compactMap({\$0})
.compactMap({\$0})
.filter({ \$0 <= 5 })
.reduce(1, *)```

Life can be easier without for/while loops!

Very nice.....

Good !!

### TomEstelrich commented Sep 30, 2019

Nice and simple way to go through all of them.