짜장이냐 짬뽕이냐,
김치찌개냐 된장찌개냐,
물복이냐 딱복이냐.
이런 논쟁들이 때론 과격해지기도 합니다.
이렇게 말이죠.
오죽하면, 인생은 B와 D사이의 C라는 말이 존재할 정도입니다.
많이들 들어보셨겠지만, Birth와 Death 사이의 Choice라는 말이죠.
아니라고요?
치킨이라고요?
어...
알파벳 기준으로 Birth와 Death 사이의 Chicken이고,
한글 기준으로 탄생(ㅌ)과 죽음(ㅈ) 사이의 치킨(ㅊ, ㅋ)이니 틀린 말이 아니긴 합니다.
치킨먹고싶네요.
뭐 여튼간에, Swift에서도 이러한 선택들이 존재합니다.
구조체를 쓸 것이냐 클래스를 쓸 것이냐,
UIKit을 쓸 것인가 SwiftUI를 쓸 것이냐,
고차함수를 쓸 것인가 반복문을 쓸 것이냐.
오늘은 고차함수와 반복문의 차이점에 대해 알아보겠습니다.
map, filter, reduce처럼 클로저(익명함수)를 전달받는 함수를 뜻합니다.
let 김치찌개: [String] = ["김", "치", "찌", "개"]
let 변형된김치찌개 = 김치찌개.map { $0 + $0 }
let 졸여진김치찌개 = 김치찌개.reduce("", +)
let 걸러진김치찌개 = 김치찌개.filter { "찌개".contains($0) }
print(변형된김치찌개) // ["김김", "치치", "찌찌", "개개"]
print(졸여진김치찌개) // 김치찌개
print(걸러진김치찌개) // ["찌", "개"]
대표적인 map, filter, reduce 말고도 더 있긴 한데 일단 3개만 예를 들었습니다.
같은 코드를 반복문으로 볼까요?
let 김치찌개: [String] = ["김", "치", "찌", "개"]
var 변형된김치찌개: [String] = []
for item in 김치찌개 {
변형된김치찌개.append(item + item)
}
var 졸여진김치찌개: String = ""
for item in 김치찌개 {
졸여진김치찌개 += item
}
var 걸러진김치찌개: [String] = []
for item in 김치찌개 {
if "찌개".contains(item) {
걸러진김치찌개.append(item)
}
}
print(변형된김치찌개) // ["김김", "치치", "찌찌", "개개"]
print(졸여진김치찌개) // 김치찌개
print(걸러진김치찌개) // ["찌", "개"]
뭐 대략 이런 느낌입니다.
그래서 둘 중 뭐가 더 빠르냐? 뭘 어떨 때 써야 하느냐?
라는 질문에는,
글로만 보니 조금 모호하죠?
차례대로 예를 들어가며 설명하겠습니다.
아래의 내용은 이 문서의 요약본이며, 원문을 읽어보시는 것을 추천드립니다.
이 문서에 따르면, 실험을 진행했을 때:
map 함수가 반복문보다 1.63배,
filter 함수가 반복문보다 1.11배 빠르지만,
reduce와 flatMap의 경우, 반복문이 각각 1.05배, 1.06배 빠른 것을 볼 수 있습니다.
다만...
let 김치찌개: [String] = ["김", "치", "찌", "개"]
// 일반적인 사용
let 변형된김치찌개 = 김치찌개.map { $0 + $0 }
let 졸여진김치찌개 = 김치찌개.reduce("", +)
let 걸러진김치찌개 = 김치찌개.filter { "찌개".contains($0) }
// 메서드 체이닝
let 변형되고졸여지고걸러진김치찌개 = 김치찌개.map { $0 + $0 }.reduce("", +).filter { "찌개".contains($0) }
print(변형된김치찌개) // ["김김", "치치", "찌찌", "개개"]
print(졸여진김치찌개) // 김치찌개
print(걸러진김치찌개) // ["찌", "개"]
print(변형되고졸여지고걸러진김치찌개) // 찌찌개개
요래... 스까서 쓰는 걸 메서드 체이닝이라고 합니다.
이렇게 위 3개의 고차함수를 섞어서 쓸 경우, 각자 O(n)의 시간복잡도를 가지고 있는 관계로 (출처), for-in을 사용한 반복문에 비해 2.37배 느린 것을 확인할 수 있습니다.
긍까 방대한 데이터를 다룰 땐 지양하는 것이 좋겠다...가 결론이 되겠군요.
이건 다음 시간에 알아보도록 하겠습니다...
참고한 페이지들:
Are higher-order functions more efficient than a for-in loop in Swift?
Swift performance: map() and reduce() vs for loops
Performance of built-in higher-order functions Map, Filter, Reduce, and flatMap vs. for-in loop in Swift
Loops and Maps : Who is faster? Time and Space complexity , we are coming!!!
[Swift] map 파헤치기