swift 기본문법 - 고차 함수(higher order function)

|

개인공부 후 자료를 남기기 위한 목적임으로 내용 상에 오류가 있을 수 있습니다.
인프런, 야곰의 스위프트 기본문법 강좌를 듣고 정리하였습니다.


고차 함수(higher order function)

전달인자로 함수를 전달받거나 함수 실행의 결과를 함수로 반환하는 함수 » map, filter, reduce

map

컨테이너 내부의 기존 데이터를 변형(transform)하여 새로운 컨테이너를 생성한다.
파라미터로 받은 클로저를 모든 요소에 실행한 그 결과를 반환

let numbers: [Int] = [0,1,2,3,4]
var doubleNumbers: [Int]
var strings: [String]

doubleNumbers = [Int]()
strings = [String]()

for number in numbers {
  doubleNumbers.append(number * 2)
  strings.append("\(number)")
}

print(doubleNumbers)  // [0,2,4,6,8]
print(strings)  // ["0", "1", "2", "3", "4"]

이를 map 메서드를 사용하여 변환해보자

doubleNumbers = numbers.map({ (number: Int) -> Int in return "(\number)"})

map의 전달인자로 클로저가 들어와 각각의 요소를 어떻게 변형해 무엇으로 돌려줄 것인지 지정이 가능하다.
Int요소를 하나하나 받아와 Int로 반환해줄 것이다. 그래서 새로운 컨테이너에 넣어달라고 할당함

매개변수, 반환타입, 반환 키워드(return) 생략, 후행 클로저 사용

doubleNumbers = numbers.map { $0 * 2 }
print(doubleNumbers)  // [0,2,4,6,8]

filter

컨테이너 내부의 값을 걸러서 새로운 컨테이너로 추출 » for 구문 사용! 변수 사용에 주목!

하나하나 요소를 필터링해서 조건에 부합하는 애들만 새로운 컨테이너로 만들어주는 것! > 필터된 값을 반환

var filtered: [Int] = [Int]()

for number in numbers {
  if number % 2 == 0 {
    filtered.append(number)
  }
}

print(filtered)  //[0,2,4]

위 예시는 for문을 만들기 위해 filtered라는 변수를 만들어줘야 했지만 filter를 사용할때는 그럴 필요가 없다.

그냥 상수로도 바로 받아올 수 있다. 변수로도 받아도 상관은 없다.

let evenNumbers: [Int] = numbers.filter {
  (number: Int) -> Bool in return number % 2 == 0
}
print(evenNumbers)  // [0,2,4]

매개변수, 반환타입, 반환 키워드(return) 생략, 후행 클로저 사용

let oddNumbers: [Int] = numbers.filter { $0 % 2 ! = 0 }
print(oddNumbers)  // [1,3]

reduce

컨테이너 내부의 콘텐츠를 하나로 통합한다.
초기값이 있고 초기값과 첫번째 요소 ~ 끝번째 요소까지의 실행된 최종 결과값만을 반환

let someNumbers: [Int] = [2,8,15]
var result: Int = 0

for number in someNumbers {
  result += number
}

print(result)  // 25

그런데 reduce메서드를 이용하면 아래와 같다.

let sum: Int = someNumbers.reduce(0, {
  (first: Int, second: Int) -> Int in return first + second
})

print(sum)  // 25
  • 초기값이 0이고
  • 모두 더해줄 것이다 라고 할때 reduce를 한다.
// 초기값이 3이고 someNumbers의 내부 모든 값을 더합니다.
let sumFromThree = someNumbers.reduce(3) { $0 + $1 }
print(sumFromThree)  // 28

sort & sorted

  • sort: 정렬하여 반환 > 원본에 영향을 줌
  • sorted: 기존 리스트를 건들지 않고 새로운 리스트에 정렬된 값을 반환

Monad

값이 있을 수도 있고 없을 수도 있는 컨텍스트를 가지는 함수객체타입이며, 함수객체와 모나드는 특정 기능이 아닌 디자인 패턴 혹은 자료구조라고 할 수 있다.

  • 컨텍스트(Context): 옵셔널처럼 값이 옵셔널 타입으로 감싸져있듯이 값을 담는 컨테이너 역할을 하는것
  • 함수객체: 맵을 적용할 수 있는 컨테이너 타입 (array, dictionary, set 등 컬렉션 타입들)

FlayMap

맵과 사용법이 같으며, 컨테이너로 쌓여져있으면 컨테이너 안의 값으로 작업을 수행하여 다시 포장하여 반환해준다.
플랫맵은 체인 형식으로 사용 가능하나 맵은 불가능 (optionals.flatMap{ $0 }.flatMap{ $0 })

let optionals: [Int?] = [0, 1, 2, nil, 4]
let map = optionals.map { $0 }
let flatMap = optionals.flatMap { $0 }

print(map) // [Optional(0), Optional(1), Optional(2), nil, Optional(4)]
print(flatMap) //[0, 1, 2, 4]