[Swift] 고차함수 (map, filter, reduce)

Kio·2022년 1월 22일
2

Swift

목록 보기
10/14

안녕하세요! Kio입니다 👻
오늘은 고차함수(Higher-order Function) 에 대해 알아볼까 하는데요.

고차함수에는 다음과 같은 여러 종류가 있습니다.
map, filter, reduce, forEach, compaceMap, FlatMap

오늘은 그 중에서 자주 쓰이는 map, filter, reduce
3가지에 대해 정리해보고자 합니다!

Let's get started 🥰




고차함수 (Higher-order Function)


고차함수란?

  • 고차함수는 다른 함수를 전달인자로 받거나 함수실행의 결과를 함수로 반환하는 함수 를 뜻합니다.

  • 스위프트의 함수(클로저)는 일급시민이기 때문에 함수의 전달인자로 전달할 수 있으며, 함수의 결과값으로 반환할 수 있습니다.

고차함수 종류

  • map
  • filter
  • reduce
  • forEach
  • compactMap
  • FlatMap




map

Returns an array containing the results of mapping the given closure over the sequence’s elements.

기존의 컨테이너의 요소에 대해 정의한 클로저로 매핑한 결과를 새로운 컨테이너로 반환합니다.


선언 (Declaration)

Apple 에서는 map 이 아래처럼 정의되어 있네요.

func map<T>(_ transform: (Element) throws -> T) rethrows -> [T]

매개변수 (Parameters)

transform

  • 매핑 클로저로, 이 컨테이너의 요소를 매개변수로 받아들이고 정의한 클로저의 형태에 맞게 변환된 값을 반환합니다.

리턴 타입 (Return Value)

이 컨테이너의 변환된 요소를 포함하는 배열을 반환합니다.


map 예시1

String 배열Int 배열
바꾸는 걸 예시 코드로 한 번 봐볼까요?!


For문으로 변환하기

let string = ["1", "2", "3", "4", "5"]
var numbers: [Int] = []
for index in string {
    if let changeToInt = Int(index) {
        numbers.append(changeToInt)
    }
}

print(numbers)
// [1, 2, 3, 4, 5]

고차함수 map으로 변환하기

let string = ["1", "2", "3", "4", "5"]
let numbers = string.map { Int($0)! }

print(numbers)
// [1, 2, 3, 4, 5]

map 예시2

이번엔 기존에 있는 Int 배열 에서
원하는 연산을 통해 새로운 Int 배열 을 반환해볼게요!


For문으로 변환하기

// numbers의 각 요소에 9 곱하기

let Numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9]
var multiplyArray: [Int] = []

for number in Numbers {
    multiplyArray.append(number * 9)
}

print(multiplyArray)
// [9, 18, 27, 36, 45, 54, 63, 72, 81]

고차함수 map 으로 변환하기

// numbers의 각 요소에 9 곱하기

let numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9]
let multiplyArray: [Int] = numbers.map { $0 * 9 }

print(multiplyArray)
// [9, 18, 27, 36, 45, 54, 63, 72, 81]

map 이 어떻게 사용되는 지 감이 오시죠?

map 은 기존의 컨테이너의 요소를 매개변수로 받아들이고 정의한 클로저의 형태에 맞게 변환된 값을 반환하기 때문에 for문보다 쉽고 간결하게 표현이 가능합니다.




filter

Returns an array containing, in order, the elements of the sequence that satisfy the given predicate.

기존 컨테이너의 요소에 대해 조건에 만족하는 값에 대해서 새로운 컨테이너로 반환합니다.


선언 (Declaration)

Apple 에서는 filter 이 아래처럼 정의되어 있네요.

func filter(_ isIncluded: (Self.Element) throws -> Bool) rethrows -> [Self.Element]

매개변수 (Parameters)

isIncluded

  • 컨테이너의 요소를 인수로 취하고, 요소가 반환된 배열에 포함되어야 하는지 여부를 Bool 값으로 반환하는 클로저입니다.

리턴 타입 (Return Value)

isIncluded 에 맞게 true 로 반환되는 값만 리턴합니다.


filter 예시1

기존의 Int 배열 에서 짝수 만 호출하는 걸 한 번 해볼게요!


For문으로 변환하기

// numbers에서 짝수만 추출하기

let numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9]
var evenNumbers: [Int] = []

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

print(evenNumbers)
// [2, 4, 6, 8]

고차함수 filter 로 변환하기

// numbers에서 짝수만 추출하기

let numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9]
let evenNumbers = numbers.filter { $0 % 2 == 0 }

print(evenNumbers)
// [2, 4, 6, 8]

filter 예시2

이번엔 기존에 있는 String 배열 에서
2글자인 String만 추출하여 String 배열 을 반환해볼게요!


For문으로 변환하기

// 2글자인 스포츠만 추출하기

let sports = ["클라이밍", "백패킹", "낚시", "러닝", "수영", "눈썰매"]
var twoLetterSports: [String] = []

for sport in sports {
    if sport.count == 2 {
        twoLetterSports.append(sport)
    }
}

print(twoLetterSports)
// ["낚시", "러닝", "수영"]

고차함수 filter 로 변환하기

// 2글자인 스포츠만 추출하기

let sports = ["클라이밍", "백패킹", "낚시", "러닝", "수영", "눈썰매"]
let twoLetterSports: [String] = sports.filter { $0.count == 2 }

print(twoLetterSports)
// ["낚시", "러닝", "수영"]

filter 가 어떤 식으로 돌아가는 지 아시겠죠?
머리가 돌아가면 안됩니다 😱

filter 는 기존의 컨테이너의 요소에서 조건에 만족하는 값에 대해서 새로운 컨테이너로 반환하기 때문에, 원하는 데이터를 추출할 때 편리하게 사용할 수 있습니다.




reduce

Returns the result of combining the elements of the sequence using the given closure.

reduce 는 정의한 클로저를 사용하여 기존 컨테이너의 요소를 결합한 결과를 반환합니다.


선언 (Declaration)

Apple 에서는 reduce 이 아래처럼 정의되어 있네요.

func reduce<Result>(_ initialResult: Result, _ nextPartialResult: (Result, Element) throws -> Result) rethrows -> Result

매개변수 (Parameters)

initialResult

  • 초기값으로 사용할 값을 넣으면 클로저가 처음 실행될 때, nextPartialResult 에 전달됩니다.

nextPartialResult

  • 컨테이너의 요소를 새로운 누적값으로 결합하는 클로저입니다.

리턴 타입 (Return Value)

최종 누적 값이 반환되며, 컨테이너의 요소가 없다면 initialResult 의 값이 반환됩니다.


reduce 예시1

Int 배열 에서 각 요소의 합을 구해볼게요!


For문으로 변환하기

// 각 요소의 합 구하기

let numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
var sum = 0

for number in numbers {
    sum += number
}

print(sum)
// 55

고차함수 reduce 로 변환하기

표현식1
// 각 요소의 합 구하기

let numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
let sum = numbers.reduce(0, +)

print(sum)
// 55
표현식2
// 각 요소의 합 구하기

let numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
let sum = numbers.reduce(0) { $0 + $1 }

print(sum)
// 55

reduce 예시2

합을 해봤으니 곱하기를 해볼까요?
Int 배열 의 각 요소를 곱셈 해보겠습니다 😆


For문으로 변환하기

// 각 요소의 곱셈 결과 구하기

let numbers = [1, 2, 3, 4, 5]
var sum = 1

for number in numbers {
    sum *= number
}

print(sum)
// 120

고차함수 reduce 로 변환하기

표현식1
// 각 요소의 곱셈 결과 구하기

let numbers = [1, 2, 3, 4, 5]
let sum = numbers.reduce(1, *)

print(sum)
// 120
표현식2
// 각 요소의 곱셈 결과 구하기

let numbers = [1, 2, 3, 4, 5]
let sum = numbers.reduce(1) { $0 * $1 }

print(sum)
// 120

reduce 를 사용하면 위의 예시처럼
누적값을 보다 용이하게 구할 수 있습니다.

reduce정의한 클로저를 사용하여 기존 컨테이너의 요소를 결합한 결과를 반환하는 고차함수 라고 기억하면 될 것 같아요!




마치면서

이렇게 고차함수에 대해 알아보았는데요!
고차함수를 활용하면 기존 for문, while문, switch문 등으로
사용했던 코드를 간결하게 줄이는 게 가능합니다.

이제 앞으로 반복문을 사용할 경우가 생기면
고차함수도 고려하여 코드를 짜보는 연습을 해보면 좋을 것 같네요 👻

  • map(_:)
  • filter(_:)
  • reduce(::)




참고

map - developer.apple
filter - developer.apple
reduce - developer.apple
yagom's Swift Basic - 고차함수




잘못된 정보가 있으면 언제든 코멘트 부탁드립니다 👻

profile
Someday_iOS_Dev

2개의 댓글

comment-user-thumbnail
2022년 7월 12일

유익한 글 잘보고 갑니다!!

답글 달기
comment-user-thumbnail
2023년 8월 9일

많은 도움이 되었습니다. 감사합니다!

답글 달기