[Swift] String은 Subscript로 접근이 안되는 이유
Updated:
String의 요소는 Int형을 파라미터로 사용해 subscript로 접근이 안되는 이유
- Collection 타입인
Array
는Int
형 index를 파라미터로 넘겨주어subscript
를 통해 해당 요소에 접근할 수 있지만,let number: [Int] = [1, 2, 3, 4, 5] number[1] // 2
String
은String.Index
구조체를 파라미터로 넘겨주어subscript
를 통해 해당 요소에 접근해야 한다.let str: String = "123456" let index = str.index(str.startIndex, offsetBy: 1) str[index] // "2" str[1] // error
Swift의 문자는 유니코드를 준수하여 표기된다
- 유니코드 문자는 크기가 가변적이기 때문에 하나의 문자가 하나의 바이트보다 클 수 있다.
- 하나의 문자가 하나이상의 바이트를 차지할 수 있기때문에, 일반적인 문자열 배열처럼(다른 언어의 문자열 배열처럼) 1 바이트 단위인 인덱스로 특정 문자에 접근할 수가 없다.
- 유니코드 표현방식으로는
utf8(8bit)
,utf16(16bit)
,utf32(32bit)
가 존재하며 Swift에서는Unicode Scalar(21bit)
가 존재한다.
*유니코드: 존재하는 모든 문자를 모든 플랫폼에 일관되게 표현하고 다룰 수 있도록 설계된 산업 표준 문자코드이다
Swift 의 String
, Character
타입은 Unicode Scalar
값으로 이루어져 있다.
- Character 타입은 하나이상의 Unicode Scalar 값으로 구성되어 있다.
let character1: Character = "\u{D55C}" // '한' let character2: Character = "\u{1112}\u{1161}\u{11AB}" // 'ᄒ, ᅡ, ᆫ' == '한'
- String 타입은 하나이상의
Character
타입(orUnicode Scalar
들)으로 구성되어 있다.let character2: Character = "\u{1112}\u{1161}\u{11AB}" // 'ᄒ, ᅡ, ᆫ' == '한' let str1 = "\u{1112}\u{1161}\u{11AB}국" // "한국" let str2 = "\(character2)국" // "한국" let str3 = "한국" // "한국"
String
은 subscript
를 통해 요소에 접근할때 순차적으로 순회한다.
- 일반적인 CollectionType(
Array
등) 은RandomAccessCollection
프로토콜을 채택하고 있어 O(1) 의 시간복잡도로 요소에 접근한다.let number = [1, 2, 3, 4, 5] number[1] // 2
String
은BidirectionalCollection
프로토콜을 채택하여 순차적으로 요소를 조회하면서 타겟 요소까지 접근하여 구성하고 있는Unicode Scalar
값의 갯수에 상응하는 O(n)의 시간복잡도가 소요된다.String
을 이루는Character
(orUnicode Scalar
들)의Unicode Scalar
값 갯수가 다를 수 있기 때문에 순차적으로Unicode Scalar
요소들을 하나하나 순회하여 하나의 문자(ex. "\u{1112}\u{1161}\u{11AB}" // "한"
)를 찾는다.
String
의 요소를 Int
형 파라미터를 사용해 subscript
로 접근할 수 있는 방법
extension String {
subscript(idx: Int) -> String? {
guard (0..<count).contains(idx) else {
return nil
}
let target = index(startIndex, offsetBy: idx)
return String(self[target])
}
}
let str = "ronick"
str[2] // "n"
str[7] // nil
Leave a comment