(침착맨의 3분할)
안녕하세요, 별똥별🌠입니다!
최근 프로그래머스 에서 알고리즘 문제를 풀어보고 있는데요. 대부분 문제의 파라미터가 string으로 주어지고 해당 string을 이리저리 변형시켜서 풀어야 하는 경우가 많았습니다.
그래서 해당 string을 변형시키려고 구글링을 했더니 swift에서 string을 나누는 두 가지 방법이 있다는걸 알았습니다.
바로 split(separator:maxSplits:omittingEmptySubsequences:)과 components인데요. 두가지가 어떻게 다른지 비교해보는 시간을 가져보도록 하겠습니다.
먼저, components(separatedBy:)는 Swift에서 문자열을 구분자(separator)로 나누는 방법이에요. 예를 들어, ","로 나누고 싶으면 이렇게 쓰면 됩니다.
let text = "apple,banana,cherry"
let components = text.components(separatedBy: ",")
print(components) // ["apple", "banana", "cherry"]
split은 StringProtocol에 있는 메서드로, 문자열을 구분자로 나누지만, 반환 타입이 다릅니다. 예를들어,
let text = "apple,banana,cherry"
let splitComponents = text.split(separator: ",")
for part in splitComponents {
print(part) // "apple", "banana", "cherry"
}
Swift에서 다른 언어들 처럼 str에 substring으로 바로 접근할 수 없습니다. 실제로
let str = "Hello"
print(str[0..<5] // 'subscript(_:)' is unavailable: cannot subscript String with an integer range, use a String.Index range instead' 에러 발생
위처럼 에러가 발생하는데 그 이유는 Swift가 문자열을 '유니코드' 기반으로 처리하기 때문입니다.
- 왜 Int 범위를 못쓰나요?
Swift는 문자열을 단순한 문자 배열로 보지 않고, 유니코드 스칼라 값(Unicode scalar values)으로 처리합니다. 예를 들어, "안녕"은 두 글자로 보이지만, 내부적으로는 더 복잡한 유니코드 코드 포인트로 구성됩니다. 즉, Int로 인덱싱하면 문자 경계가 어긋날 수 있어 안전하지 않습니다. 대신 String.Index를 사용해야합니다.
- 다른 언어와의 차이
Python이나 JavaScript에서는 str[0]처럼 Int로 바로 접근할 수 있지만, Swift는 문자열의 복잡성을 고려해 더 엄격한 접근 방식을 채택했습니다. 이는 유니코드 지원과 문자열 안정성을 보장하기 위한 설계 철학입니다. 예를 들어, 이모지(😀)나 복합 문자(é)를 다룰 때, Int 인덱싱은 잘못된 결과를 초래할 수 있습니다.
- 올바른 방법
String.Index는 문자열의 실제 위치를 나타내는 타입으로, startIndex와 index(_:offsetBy:)를 사용해 접근합니다. 예를 들어,let str = "hello,world" let start = str.startIndex let end = str.index(start, offsetBy: 5) let substr = str[start..<end] // "hello" as Substring let converted = String(substr) // "hello" as String print(converted) // "hello"이렇게 하면 안전하게 문자열을 자를 수 있습니다.
| 특성 | components(separatedBy:) | split(separator:) |
|---|---|---|
| 반환 타입 | [String] (새로운 문자열) | [SubString] (원본 참조) |
| 메모리 사용 | 높음 (복사 발생, 메모리 부담 큼) | 낮음 (복사 없음, 메모리 효율적) |
| 성능 | 큰 문자열에서 느릴 수 있음 | 큰 문자열에서 효율적 |
| 사용 용이성 | 바로 [String] 사용 가능 | SubString -> String 변환 필요 |
| 적합한 경우 | 작은 문자열, 결과 저장 필요 | 큰 문자열, 임시 처리, 메모리 최적화 필요 |
Swift의 split과 components는 비슷해 보이지만, 반환 타입과 메모리 사용 방식에서 차이가 있습니다. 특히 String을 자를 때 Int 범위를 못쓰는 이유는 Swift의 유니코드 처리 방식 때문입니다. String.Index를 사용하면 안전하게 문자열을 다룰 수 있습니다. 이 차이를 이해하면 상황에 맞게 더 효율적으로 코드를 작성할 수 있습니다!