[TIL]08.20

rbw·2022년 8월 20일
0

TIL

목록 보기
39/97
post-thumbnail

문자열에 인덱스로 접근하는 extension

이번에 코딩테스트를 Swift로 해보려고 해서 찾아본 코드 !

문자열을 다룰 떄 유용하게 사용하지 싶다.

extension String {
    subscript(_ index: Int) -> Character {
        return self[self.index(self.startIndex, offsetBy: index)]
    }
}

// 얘는 범위 설정 가능
extension String {
    subscript(_ range: Range<Int>) -> String {
        let fromIndex = self.index(self.startIndex, offsetBy: range.startIndex)
        let toIndex = self.index(self.startIndex,offsetBy: range.endIndex)
        return String(self[fromIndex..<toIndex])
    }
}

Swift 문자열 접근의 시간 복잡도 문제

좀 더 찾아보니, Swift의 문자열에서는 word[index] 이렇게 접근하는 것만으로도 O(n) 의 시간 복잡도를 가진다고 한다. 결국 위의 Extension도 시간 복잡도적인 문제는 여전히 존재한다고 보면 된다.

그래서 생각한 방법은 Array로 만들어서 해당 문자에 접근을 하고 다시 String으로 만들던가 하는 경우가 시간 복잡도 면에서는 유리하다고 생각한다.

물론 문자열 내부 문자에 접근하는 경우가 많다면 시도 하는게 좋고, 그렇지 않다면 추천하지는 않는다. 이렇게 생각하게된 계기로는, 만약 문자 전체에 접근하는 코드를 작성한다면 단순히 생각 했을때 O(n^2)의 복잡도를 가지므로 배열로 형변환 후 접근을 한다음 문자열로 접근하는 것은 O(2n+m) 이라고 생각하기 때문이다.

O(n^2)인 이유는 하나의 문자에 접근하는 시간 O(n) 전체 문자수 n 따라서 O(n * n)이 나옵니다.

  • 문자열을 배열로 형변환 -> O(n)
  • 배열에서의 첨자 접근 횟수 M(전부 접근 시 n) -> `O(1) M`
  • 배열을 문자열로 형변환 -> O(n) 따라서 O(2n + M)

제 생각이 틀릴수도 있기 때문에 너무 맹신하시면 안되지만, 저의 짧은 생각으로는 형변환의 방식이 O(n^2)는 절대 걸리지 않는다라고 생각했습니당.

힙에 저장되는 변수의 다중 인스턴스 생성을 피하는 방법

스위프트 성능에 대해서 알아 보던 중, 힙에 저장되는 참조 유형(클래스, 문자열 등)의 다중 생성을 피하는 방법에 대해서 나와 있는 글을 보고 정리하려고 합니다.

문자열은 스택에 저장되는 경우도 있고 힙 영역에 사용되는 경우도 있습니다 ! - 김정님 Medium

예를 들어 함수 내부의 변수에 문자열을 할당하고 이를 여러 번 호출해야하는 경우에 힙에 자주 저장되는 문제가 있다 이는 성능을 저하시키는 요인이 된다.

enum Color { case blue, green, gray }
enum Orientation { case left, right }
enum Tail {case none, tail, bubble }

var cache = [String : UIImage]()

func something(color: Color,orientation: Orientation, tail: Tail) -> UIImage{
    let key = "\(color):\(orientation):\(tail)"
    if let image = cache[key] {
        return image
    }
}

위 코드는 키가 문자열인 이미지 맵이 있고, 다운로드하거나, 캐시에서 가져와야 한다는 경우에 문자열 키를 생성하는 함수를 계속 호출해야 합니다. 이는 힙에 저장하는 빈도가 늘어나므로 좋지 않습니다.

이 부분을 해결하는 방법으로는 현재 key의 문자열을 구조체로 만들면 해결이 됩니다. 구조체를 만드는 것은 스택에 할당되며, 시간이 많이 걸리는 프로세스가 아니기 때문에 성능향상에 많은 도움이 됩니다

// cache의 key 타입을 구조체로 받음 
var cache = [Attributes : UIImage]()

struct Attributes: Hashable {
    var color: Color
    var orientation: Orientation
    var tail: Tail
}

func something(color: Color, orientation: Orientation, tail: Tail) -> UIImage {
    let key = Attribute(color: color, orientation: orientaion, tail: tail)
    ...
}

참조

https://medium.com/macoclock/swift-struct-vs-class-performance-29b7be73d9fd

https://onemoonstudio.tistory.com/15?category=845836

https://medium.com/@jungkim/%EC%8A%A4%EC%9C%84%ED%94%84%ED%8A%B8-%ED%83%80%EC%9E%85%EB%B3%84-%EB%A9%94%EB%AA%A8%EB%A6%AC-%EB%B6%84%EC%84%9D-%EC%8B%A4%ED%97%98-4d89e1436fee

profile
hi there 👋

0개의 댓글