Tech/Swift

스위프트 문자열에서 숫자 뽑아내기

Ellie Kim 2019. 10. 16. 23:55

문자열에 " " , "-"값이 포함될 수 있으며 이것을 무시하고 숫자만 필터링해내는 작업을 처리해줘야 했습니다.

예를 들어 "010-1111-2222"인 문자열이 들어오면 "01011112222"와 같이 숫자만 뽑아내고

"010 1111 2222"인 문자열이 들어오면 이 또한 "01011112222"로 숫자만 뽑아내야 합니다.

 

replacingOccurrences(of: with:)

처음에는 문자열 바꿔치기에 자주 사용했던 replacingOccurrences(of: with:) 메소드를 사용해 " "그리고 "-"값을 빈칸으로 만들어 주도록 했습니다.

let filterStr = originalStr.replacingOccurrences(of: " ", with: "").replacingOccurrences(of: "-", with: "")

이렇게요.

나 왜그랬지 ㅎㅎㅎ핳ㅎ핳

여하튼 처음에는 replacingOccurrences(of: with:)를 이중으로 사용했습니다.

func replacingOccurrences(of target: String, with replacement: String) -> String

먼저 replacingOccurrences(of: with:) 함수를 살펴보겠습니다.

replacingOccurrences(of: with:)는 타겟 스트링을 대체할 스트링으로 변경해 새로운 문자열을 리턴해주는 메소드입니다.

이는 원소의 개수만큼 N 돌면서 교체하는 상수의 시간이 걸리고 때문에 최종적으로 시간 복잡도는 O(n)가 됩니다.

저는 총 두 번의 replacingOccurrences(of: with:)를 사용했기 때문에 먼저 " "를 ""으로 바꾸고 새로운 문자열을 리턴해주는 그 문자열을 가지고 또 한 번 "-"를 ""으로 바꾸어 새로운 문자열을 리턴해주는 방법을 사용했기 때문에 이는 비효율적인 방법이라고 할 수 있습니다. 

 

정규표현식으로 할 경우 두 번 replaceingOccurences를 사용할 필요가 없어 이전보다 개선할 수 있었습니다.

let filterStr = originalStr.replacingOccurrences(of: " |-", with: "",options: .regularExpression)

 

compactMap

 

숫자를 필터링하는 또 다른 방법은 compactMap을 사용하는 방법입니다.

func compactMap<ElementOfResult>(_ transform: (Self.Element) throws -> ElementOfResult?) rethrows -> [ElementOfResult]

공식문서를 살펴봅니다.

공식문서 예제를 보니 머리에 더 잘 들어오네요.

예제에서는 String 배열이 존재하고 각 Element를 Int로 변환해 새로운 배열을 리턴합니다.

map과 compactMap과의 차이는 nil이 포함되냐 안되냐의 차이입니다.

 

그럼 compactMap를 사용해 숫자만 필터링할 수도 있겠네요.

들어온 문자열을 문자열 배열로 만든 후 compactMap을 사용해 숫자만 필터링 할 수 있습니다.

let filterArr = originalStrArr.compactMap { str in 
	Int(str)
 }

https://developer.apple.com/documentation/swift/sequence/2950916-compactmap

 

filter

숫자를 필터링하는 또 다른 방법은 filter를 사용하는 방법이 있습니다.

스위프트 5에서 Character 속성에 새롭게 추가된 내용이 있습니다.

여러 가지가 있겠지만 그중에서도 isNumber을 활용해서 문자를 숫자를 뽑아낼 수도 있겠네요.

let filterStr = originalStr.filter { $0.isNumber }

https://github.com/apple/swift-evolution/blob/master/proposals/0221-character-properties.md

 


이말고도 CharacterSet.decimalDigits.inverted를 사용하는 방법도 있습니다.

또한 유니코드 스칼라를 사용하는 방법도 있습니다. 

이런 방법이 있고, 저런 방법이 있으니 여러 가지를 비교하고 사용해보는 것이 좋을 것 같습니다.

 

PS

앞으로 신경 써서 더 효율적인 코드로 만들자.