DADAHAE's Log
비싼 장난감 가지고 노는 중 (❁´▽`❁)*✲゚*
Swift에서 For loop(반복문)와 map 함수의 속도는 진짜 차이가 날까..? | 프로그래머스 Lv.0: 배열 두 배 만들기(Swift, Python)

도입

요즘 프로그래머스에서 Swift와 Python으로 문제를 풀고 있다. 단계가 낮은 것부터 풀어보면서 모르는 것들을 해결하고 있는데...

'배열 두 배 만들기' 문제를 풀다가 반복문과 map함수의 속도 차이가 궁금해졌다. 

Swift에서 보면 고차함수 써라~ map 써라~ 라고 하는데 사실 와닿지가 않았다.

 

그래서 프로그래머스에서 문제를 제출하면 매겨주는 속도로 반복문과 map의 차이를 비교해보기로 했다.

 

 

Programmers Lv.0: 배열 두 배 만들기

https://school.programmers.co.kr/learn/courses/30/lessons/120809

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

 

반복문으로 아이템들의 값을 2배로 해주거나, map으로 하나씩 뽑아서 해주거나.

결국 푸는 자가 승리하는게 코테긴 한데, 연습할 때는 다양하게 풀어보자.

 

1. 문제 분석

Swift에서 반복문을 사용하여 풀어보았다.

 

(1) 빈 배열에 append하는 것(2) 미리 초기화한 배열에 값을 할당하는 것과 무엇이 더 빠를까 궁금해졌다.

// 빈 배열에 새로운 값 append
func solution(_ numbers:[Int]) -> [Int] {
    var answer: [Int] = []
    for num in numbers {
        answer.append(num*2)
    }
    return answer
}

// 이미 초기화된 배열에 새로운 값 할당
func solution(_ numbers:[Int]) -> [Int] {
    var answer: [Int] = numbers
    for (index,num) in numbers.enumerated() {
        answer[index] = num*2
    }
    return answer
}

왼쪽이 (1), 오른쪽이 (2)의 결과이다.

나는 당연히 기존 값에 할당하는게 더 빠를거라고 생각했는데, 빈 배열에 append하는게 더 빨랐다!! 와아…

enumerated()를 써서 느린걸까?

 

그래서 enumerated()를 안쓰고, index를 따로 만들어줘서 +1을 하는 방식으로 돌려봤더니…

import Foundation

func solution(_ numbers:[Int]) -> [Int] {
    var answer: [Int] = numbers
    var index = 0
    for num in numbers {
        answer[index] = num*2
        index += 1
    }
    return answer
}

이게 왠걸, 더 빠르다! append를 하는 방식보다 훨씬 빨랐다!

 

결국 할당하는 것 자체가 더 빠르긴한데, enumerated()와 같은 index 계산 메서드를 쓰면 여기에 시간이 더 소모되서… 연산이 오래 걸리는 것이었다.

 

 

근데 이것보다 압도적인게 있었다. 과연 map 함수는?

func solution(_ numbers:[Int]) -> [Int] {
    return numbers.map{ $0 * 2 }
}

Swift에서 map 함수가 반복문보다 훨-씬 빠르다.

진짜 수가 커질수록 너무 차이가 난다. 왜 Swift에서 map을 쓰라고 하는지 경험적으로 알게 되었다.

 

 

아래는 map 함수에 대해서 알아본 자료이다!

https://www.skoumal.com/en/performance-of-built-in-higher-order-functions-map-filter-reduce-and-flatmap-vs-for-in-loop-in-swift/

https://www.linkedin.com/pulse/loops-maps-who-faster-time-space-complexity-we-coming-george-michelon/

https://sujinnaljin.medium.com/swift-map-파헤치기-4b057834d310

 

 

2. 문제 풀이

Swift, Python 2가지로 풀었다.

  • Swift
import Foundation

// 빈 배열에 새로운 값 append
func solution(_ numbers:[Int]) -> [Int] {
    var answer: [Int] = []
    for num in numbers {
        answer.append(num*2)
    }
    return answer
}

// 이미 초기화된 배열에 새로운 값 할당
func solution(_ numbers:[Int]) -> [Int] {
    var answer: [Int] = numbers
    for (index,num) in numbers.enumerated() {
        answer[index] = num*2
    }
    return answer
}

// enumerated를 쓰지않고, 직접 index 카운팅
func solution(_ numbers:[Int]) -> [Int] {
    var answer: [Int] = numbers
    var index = 0
    for num in numbers {
        answer[index] = num*2
        index += 1
    }
    return answer
}

 

  • Python
def solution(numbers):
    answer = []
    for num in numbers:
        answer.append(num*2)
    return answer

 

 

3. 다른 풀이

여기서부터는 내가 푼게 아니라, 다른 사람들의 풀이 중 기억에 남는 것을 가져온 것이다.

 

  • Swift
    • map
import Foundation

func solution(_ numbers:[Int]) -> [Int] {
    return numbers.map({ $0 * 2 })
}

역시 고차함수!

 

  • Python
    • list []
    • lambda + map
    • numpy
def solution(numbers):
    return [num*2 for num in numbers]
def solution(numbers):
    return list(map(lambda x: x * 2, numbers))
import numpy as np

def solution(numbers):
    answer = []
    answer = np.array(numbers)*2
    answer = answer.tolist()
    return answer

이 문제를 풀면서 가장 먼저 생각난건 반복문이었고, 그 다음 numpy였다. numpy를 쓰면 개별 값에 연산이 된다는 것만 알았지 쓰는 방법을 몰라서 못풀었다.

그리고 다른 방법들도 무조건 존재할거라고 생각했다. 역시 있었다.

배열 내부적으로 계산해서 아이템을 쌓는 방법, lambda식과 map으로 푸는 방법…

역시 다양했다. 특히 람다 방식은 아직 익숙하지 않아서 좀 봐둬야겠다. lambda + map은 마치 Swift의 map함수의 느낌도 난다. 비슷하다!!

'공부 > Swift' 카테고리의 다른 글

[Swift] 'Stack' Data Structure  (0) 2022.08.02
  Comments,     Trackbacks