We could see Concept of Closure from Closure (Concept)

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:

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

### Example:

```
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:

```
let returnedArray = anyArrays.map { elementOfArray in
statements
}
```

### Example 1 : below example return new string array from string array

```
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 🤩

```
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:

```
let returnedArray = anyArrays.compactMap { elementOfArray in
statements
}
```

### Example:

```
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:

```
let returnedArray = anyArrays.flatMap { elementOfArray in
statements
}
```

### Example:

```
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:

```
let returnedArray = anyArrays.filter { elementOfArray in
condition statements
}
```

### Example:

```
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:

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

### Example:

```
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:

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

### Example:

```
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:

```
inputArray.sort()
```

### Example:

```
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:

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

### Example

```
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:

```
let newArray = inputArray.sorted()
```

### Example:

```
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:

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

### Example:

```
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]
```

## Discussion (0)