[오늘의 Swift 지식] 고차 함수 (map, filter, reduce)

2022. 2. 1. 13:44·📌 Swift
-->

고차 함수란?

고차 함수(Higher-Order Function)는 하나 이상의 함수를 인자로 받거나, 함수를 결과로 반환하는 함수를 말합니다.

 

스위프트에서 제공하는 고차함수는 map, filter, reduce 3가지가 있으며, 컬렉션을 처리할 때 매우 유용합니다.

 

 

map(변형)

map 메서드는 컨테이너 내부에 각 요소를 변형(transform)하여 새로운 컨테이너를 생성합니다.

다만, 새로운 컨테이너를 생성한 것이기 때문에 기존의 데이터는 변하지 않습니다.

 

map은 for-in 구문과 유사한 결과를 만들지만, 코드가 더 간결하고 선언적으로 작성할 수 있다는 장점이 있습니다.

 

그러면, for-in 문과 map 메서드를 사용한 코드를 비교해보겠습니다.

 

for-in

let numbers: [Int] = [0, 1, 2, 3]
var doubleNumbers: [Int] = []
for number in numbers {
	doubleNumbers.append(number * 2)
}

print(doubleNumbers) // [0, 2, 4, 6]
// 새로 생성한 것이기 때문에 numbers의 데이터는 변하지 않음.
print(numbers) // [0, 1, 2, 3]

 

map

let numbers: [Int] = [0, 1, 2, 3]
let doubleNumbers: [Int] = numbers.map { (number: Int) -> Int in
	return number * 2
}

print(doubleNumbers) // [0, 2, 4 ,6]
// 마찬가지로, numbers의 데이터는 변하지 않음.
print(numbers) // [0, 1, 2, 3]

위의 코드처럼, map 메서드를 사용하면 코드가 더욱 간결해지는 걸 볼 수 있습니다.

 

또한, 위의 코드에서 매개변수 및 반환 타입, 반환 키워드(return)를 생략하고, 후행 클로저를 사용하면 아래와 같이 코드가 더욱 간략해진 걸 볼 수 있습니다.

 

map 축약

let numbers: [Int] = [0, 1, 2, 3]
let doubleNumbers: [Int] = numbers.map { $0 * 2 }

print(doubleNumbers) // [0, 2, 4, 6]
// 동일하게 numbers의 값은 [0, 1, 2, 3]으로 기존의 데이터는 변하지 않음.

 

 

filter(추출)

filter 메서드는 컨테이너 내부의 요소 중 조건을 만족하는 값만 걸러내어, 새로운 컨테이너로 반환합니다.

 

클로저의 반환 타입은 Bool 타입이며, true를 반환하는 요소만 결과 컨테이너에 포함됩니다.

 

이번에도 for-in 문과 filter 메서드를 비교해봅시다!

 

for-in

let numbers: [Int] = [0, 1, 2, 3, 4, 5]
var evenNumbers: [Int] = []
for number in numbers {
	if number % 2 == 0 {
		evenNumbers.append(number)
	}
}
print(evenNumbers) // [0, 2, 4]
print(numbers) // [0 ,1, 2, 3, 4, 5]

 

filter

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

이처럼 filter 메서드를 사용하면 for-in 문에 비해 코드가 보기 쉽고 간략화된 것을 볼 수 있습니다.

 

그리고 filter 또한 아래처럼 축약하여 사용할 수 있습니다.

 

filter 축약

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

 

 

reduce(결합)

reduce 메서드는 컨테이너 내부의 요소들을 지정한 방식으로 하나의 결과값으로 결합시켜줍니다.

 

첫 번째 매개변수를 통해 초기값을 지정해줄 수 있으며, 정수 배열이라면 연산 결과를 합치고 문자열 배열이라면 문자열을 하나로 통합하는 일을 해줍니다.

 

for-in

let numbers: [Int] = [0, 1, 2, 3, 4, 5]
var reduceResult: Int = 0
for number in numbers {
	reduceResult += number
}
print("reduceResult: \(reduceResult)") // reduceResult: 15
print(numbers) // [0, 1, 2, 3, 4, 5]

 

reduce

let numbers: [Int] = [0, 1, 2, 3, 4, 5]
let reduceResult: Int = numbers.reduce(0) {
	(result: Int, next: Int) -> Int in
	print("\(result) + \(next)")
	return result + next
}

print("reduceResult: \(reduceResult)")
// 0 + 0
// 0 + 1
// 1 + 2
// 3 + 3
// 6 + 4
// 10 + 5
// reduceResult: 15

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

이 부분은 조금 헷갈릴 수 있으니 설명을 더 적어볼게요 😋

 

numbers 배열에 초기값을 만들어준 후, reduce 메서드 첫 번째 매개변수의 초기값을 0으로 설정해주었으며, 두 번째 매개변수 클로저를 보면 result와 next를 더해서 Int 형태로 반환해주는 코드입니다.

 

이렇게 되면 numbers배열에 있는 각 요소들은 더해지며 reduceResult 변수에 대입됩니다. (여기서 result는 이전 단계까지의 누적값을, next는 현재 처리중인 요소를 의미합니다.)

 

만약, 초기값인 numbers.reduce(0)를 numbers.reduce(5)로 변경해 주었을 경우, 초기값이 0이 아닌 5이기 때문에 출력 결과는 아래와 같이 나오게 됩니다.

print("reduceResult: \(reduceResult)")
// 5 + 0 = 5
// 5 + 1 = 6
// 6 + 2 = 8
// 8 + 3 = 11
// 11 + 4 = 15
// 15 + 5 = 20
// reduceResult: 20

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

또한, reduce도 map과 filter와 마찬가지로 아래와 같이 생략하여 축약 표현이 가능합니다. 👍

 

reduce 축약

let numbers: [Int] = [0, 1, 2, 3, 4, 5]
let reduceResult: Int = numbers.reduce(0) { $0 + $1 }
print(reduceResult) // 15
print(numbers) // [0, 1, 2, 3, 4, 5]

 

 

 

마지막 정리!

메서드 역할 반환 값 사용 예시
map 각 요소를 변형 새로운 컨테이너 [1, 2, 3].map { $0 * 2 } -> [2, 4, 6]
filter 조건에 맞는 요소 추출 새로운 컨테이너 [1, 2, 3].filter { $0 % 2 == 0 } -> [2]
reduce 요소들을 하나의 값으로 결합 단일 값 (Int, String 등) [1, 2, 3].reduce(0) { $0 + $1 } -> 6

 

 

 

공부한 내용을 바탕으로 정리하다 보니, 오타나 틀린 내용이 있을 수 있습니다.
틀린 내용이나 오타는 댓글로 알려주시면 감사하겠습니다 :)

 

 

 

 

'📌 Swift' 카테고리의 다른 글

[오늘의 Swift 지식] max(), min()으로 최대/최소값 구하기  (0) 2025.04.07
[Swift] 문자열 나누기 split()과 components() 를 알아보자!  (0) 2022.03.29
[오늘의 Swift 지식] stride 함수 (백준 2742번 기찍 N, 역수 구하기)  (0) 2021.10.24
[오늘의 Swift 지식] In-Out이란 무엇일까?  (0) 2021.08.24
[오늘의 Swift 지식] 전달인자(Argument)와 매개변수(Parameter)  (0) 2021.08.13
'📌 Swift' 카테고리의 다른 글
  • [오늘의 Swift 지식] max(), min()으로 최대/최소값 구하기
  • [Swift] 문자열 나누기 split()과 components() 를 알아보자!
  • [오늘의 Swift 지식] stride 함수 (백준 2742번 기찍 N, 역수 구하기)
  • [오늘의 Swift 지식] In-Out이란 무엇일까?
MoriOS
MoriOS
기억하기 위해 기록하는 공간 🖋️
  • MoriOS
    MoriOS
    MoriOS
  • 전체
    오늘
    어제
    • 분류 전체보기 (38) N
      • 📌 Swift (10)
      • 📱 iOS (4)
      • 💡 Algorithm (1)
      • ❕Data structure (4)
      • 🪙 Python (0)
      • ⚙️ Git (2)
      • 🖋️ TIL Journal (14) N
      • 📝 Etc (3)
  • 블로그 메뉴

    • GitHub
  • 인기 글

  • 태그

    swift 대소문자
    swift 아스키
    todo 앱
    Split
    swift 최대 최소
    weak
    swift optional
    후행클로저
    swift min
    터미널 기본 경로
    iterm2 기본 경로
    swift
    Optional
    weak vs unowned
    터미널 워킹 디렉토리
    TiL
    ios segue
    swift 알고리즘 팁
    swift max
    낼배캠 사전 캠프
    강한 참조
    낼배캠
    ios
    iterm 실행 폴더
    ios 데이터 저장
    joined()
    todo앱
    Components
    swift 수학
    swift ismultiple
  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
MoriOS
[오늘의 Swift 지식] 고차 함수 (map, filter, reduce)
상단으로

티스토리툴바