Closure(Handy methods)
Tags: swift, reduce, sort, map
Published: 2021-10-17 14:15:57

We could see Concept of Closure from [Closure (Concept)](https://dev.to/danieljang/closure-concept-3529)

Collections have several handy methods by using closure syntax.
Let’s study how Closure can be useful when dealing with collections.

#forEach
* forEach doesn’t return anything

###syntax:
```swift
anyArrays.forEach { elementOfArray in
  print(elementOfArray)
}

//Same performance as for ~ in loop
for elementOfArray in anyArrays {
  print(elementOfArray)
}
```

###Example:
```swift
var nameArray = ["Daniel", "Billy", "Gon"]
nameArray.forEach { name in
    print(name)
}
//or
nameArray.forEach { print($0) }
/*Result
 Daniel
 Billy
 Gon*/
 
  
var integerArray = [1, 2, 3]
integerArray.forEach{ print($0) }
/*Result
 1
 2
 3*/
```
---
---



#map
* map returns an array

###syntax:
```swift
let returnedArray = anyArrays.map { elementOfArray in
  statements
}
```
###Example 1 : below example return new string array from string array
```swift
var nameArray = ["Daniel", "Billy", "Gon"]
let returnedNameArray = nameArray.map { name in
    name.uppercased()   //TIP: you can remove return keyword when statement is singline in curly brace
}
//or same as below
let returnedNameArray = nameArray.map { $0.uppercased() }

//Result: returnedNameArray = ["DANIEL", "BILLY", "GON"]
```
###Example 2: below example return new string array from integer array (i.e. based on your statement you can convert your original array to other type’s array 🤩
```swift
let numbers = [2, 4, 6]
let stringNumbers = numbers.map { number -> String in   
    "count is \(number)"  //TIP: return keyword is removed becuase of statement is singline
}
//or
let stringNumbers = numbers.map { number in   
    "count is \(number)"
}
//or
let stringNumbers = numbers.map {  "count is \($0)"  }

//Reesult: stringNumbers = ["count is 2", "count is 4", "count is 6"]
```
---
---



#compactMap
* compactMap return array without “nil” value

###syntax:
```swift
let returnedArray = anyArrays.compactMap { elementOfArray in
  statements
}
```
###Example:
```swift
let stringArray = ["3.14", "20.5", "Daniel"]

let integerArray = stringArray.compactMap{ element in
    Double(element)
}

//Result: integerArray = [3.14, 20.5]
// stringArray have 3 element
// first element(3.14) can be converted to Double by Double("3.14")
// second element(20.5) can be converted to Double by Double("20.5")
// BUT third element "Daniel" cannot be converted to Double. Double("Daniel") is nil value 
```
___
___



#flatMap
* return combined single dimension array from multi dimension input array

###syntax:
```swift
let returnedArray = anyArrays.flatMap { elementOfArray in
  statements
}
```
###Example:
```swift
let multiDimensionArray = [ ["Apple", "Tomato", "Banana"], ["100", "200", "300"] ]
let combinedArray = multiDimensionArray.flatMap { $0 }

//Result: combinedArray = ["Apple", "Tomato", "Banana", "100", "200", "300"]
```
---
---



#filter
* return array with passed elements when condition statement is true in closure

###syntax:
```swift
let returnedArray = anyArrays.filter { elementOfArray in
  condition statements
}
```

###Example:
```swift
let inputScore = [ 34, 14, 68, 70, 23, 90, 95]
let passedScore = inputScore.filter { score in
    score > 50
}

//Result: passedScore = [68, 70, 90, 95]
```
---
---


#reduce
* return “Result” can be any types
* reduce have 2 arguments, first is initial vlaue and sencond is closure with return Result
* Closure which is second argument has return data type same as initialValue’s data type
* Closure returns Result and closure’s first value get the return value until last element
* closure:(Result,Any) -> Result)

###syntax:
```swift
let returnedValue = anyArrays.reduce(initialValue: Result, closure:(Result,Element) -> Result)
```

###Example:
```swift
let inputScore = [ 34, 14, 68, 70, 23, 90, 95]
//first argument(0) is initial valye and second argument is closure
//total is as stored property with 0 initial value
//score is element of inputScore array
let sumScore = inputScore.reduce(0, { total, score in  
    total + score
})

//Let's change format by trailling closure
let sumScore = inputScore.reduce(0) { total, score in  
    total + score
}

//Result: sumScore = 394
```
---
---



#reduce(into:)
* return “Result” can be any types
* reduce have 2 arguments, first is initial vlaue and sencond is closure without return Result(Closure doesn’t return anything)
* Closure’s first argument has “inout” label. That means the argument is mutable(we will store value to the first argument “Result”
* “initialValue”’s data type and first argument’s data type of “closure” are same.

###syntax:
```swift
let returnedValue = anyArrays.reduce(initialValue: Result, closure:(inout Result, Element) -> ( ))
```

###Example:
```swift
var inputDic = [1: 3.5, 2: 6, 3: 4.4]

// [] is initial array, element is element of inputDic
var outputArray = inputDic.reduce(into: []) { partialResult, element in   
    partialResult.append(Double(element.key) * Double(element.value))
}

//Result: outputArray = [3.5, 12.0, 13.200000000000001]
```
---
---



#sort
* sorting ascending order
* reassign return array to  input array itself

###syntax:
```swift
inputArray.sort()
```

###Example:
```swift
var numbers = [3, 5, 1, 4, 6, 2]
numbers.sort()

//Result: numbers = [1, 2, 3, 4, 5, 6]
```
---
---


#sort(by:)
* sorting by “by” argument(closure)
* reassign return array to  input array itself

###syntax:
```swift
inputArray.sort(by: (element, element) throws -> Bool)
//or
inputArray.sort { element, element in
  condition statement
}
```

###Example
```swift
var numbers = [3, 5, 1, 4, 6, 2]
numbers.sort { a, b in
    a > b
}
//or
numbers.sort { $0 > $1 }
//or
number.sort(by: >)

//Result: numbers = [6, 5, 4, 3, 2, 1]
```


#sorted
* sorting ascending order
* assign return array to  new array
* original input array value is no-change

###syntax:
```swift
let newArray = inputArray.sorted()
```

###Example:
```swift
var numbers = [3, 5, 1, 4, 6, 2]
let newNumbers = numbers.sorted()
//Result
//numbers = [3, 5, 1, 4, 6, 2]
//newNumbers = [1, 2, 3, 4, 5, 6]
```
---
---



#sorted(by:)
* sorting by “by” argument(closure)
* assign return array to  new array
* original input array value is no-change

###syntax:
```swift
let newArray = inputArray.sorted(by: (element, element) throws -> Bool)
//or
let newArray = inputArray.sorted{ element, element in
  condition statement
}
```

###Example:
```swift
var numbers = [3, 5, 1, 4, 6, 2]

let newNumbers = numbers.sorted { a, b in
    a > b
}
//or
let newNumbers = numbers.sorted { $0 > $1 }
//or
let newNumbers = numbers.sorted(by: >)

//Result
//numbers = [3, 5, 1, 4, 6, 2]
//newNumbers = [6, 5, 4, 3, 2, 1]
```

###Yea~~~~ Done !!!