๐ Swift ์์ ๋ฌธ์์ด index ์ ๊ทผ์ ๋ํ์ฌ
Swift ์์ ๋ฌธ์์ด์ ์ด๋ป๊ฒ ์กฐํํ ๊น ?
swift์์ ๋ฌธ์์ด์ ์ ์ index๋ก ์กฐํํ๋ฉด ์ค๋ฅ๊ฐ ๋ฐ์ํ๋ค.
๊ทธ๋ฌ๋ฉด Swift์์๋ ์ด๋ค ๋ฐฉ์์ผ๋ก ์กฐํํด์ผ ํ ๊น ?
String.Index๋ฅผ ์ฌ์ฉํด์ ์ ๊ทผํ๋ค.
// ์ ์ธ
let str = "hello world!"
// ์กฐํ
str[str.startIndex] // 'h'
str[str.endIndex] // '!'๊ฐ ๋์ฌ์ง ์์๊ฒ ์ง๋ง ์๋ฌ ๋ฐ์
var idx = str.index(str.startIndex, offsetBy: 6)
str[idx] // 'w'
// ๋ฐ๋ณต๋ฌธ์ ์ธ๋ฑ์ค์ฒ๋ผ ๋ฝ์ ์ฌ์ฉํ๋ ค๋ฉด indicies ๋ฉ์๋ ์ฌ์ฉ
for i in str.indices {
print(str[i]) // Index(_rawBits:) ๊ฐ์ด ์ถ๋ ฅ๋๋ค.
}
Java๋ฅผ ๋ง์ด ์ฌ์ฉํด์๋ ๋ด๊ฐ ์ด๊ฑธ๋ณด๋ฉด ํ๋ง๋๊ฐ ๋์จ๋ค.
์๋ ์?
hello world!๋ผ๋ ๋ฌธ์์ด์์ w๋ฅผ ์ ๊ทผํ๋๋ฐ Pythob์์๋ str[6]์ด๋ฉด ๋๋ฌ๋๋ฐ, Swift์์๋ str[str.index(str, offsetBy:6)์ ํด์ผ ๋น๋ก์ ๊ธ์ ํ๋์ ์ ๊ทผํ ์ ์๋ค.
๊ฒ์ผ๋ก๋ง ๋ณด๋ฉด str str str... ๋ณ์๋ช ์ ๋ฌด๋ ค ์ธ๋ฒ์ด๋ ์ฌ์ฉํ๋ค.
๋ถ๋ช ํ C, C++ ์ธ์ด๋ถํฐ ์ ์ ์ธ๋ฑ์ค๋ก ์ ๊ทผํ๋ ํจ์จ์ ์ธ ๋ฐฉ๋ฒ์ด ์ด๋ฏธ ์๋๋ฐ, ํ๋ ์ธ์ด์ ํจ๋ฌ๋ค์์ ์์ด๋์๋ค๋ Swift์์๋ ์ ์ด๋ฐ ๋นํจ์จ์ด ์๊ธด๊ฑธ๊น
Swift์ ๋ฌธ์ ์ ์ฅ ๊ตฌ์กฐ
์์ ์ธ์ด๋ค์ ๋ฌธ์์ด์ ๊ฐ๊ฐ ์ธ๋ฑ์ค๋ง๋ค ๋์ผํ ํฌ๊ทธ์ ๋ฐ์ดํฐ ๊ฐ์ ๊ฐ์ง๊ณ ์์๋ค. Swift ๊ณต์๋ฌธ์์ ๋ฐ๋ฅด๋ฉด, Character ํ์ ์ ๋ฐ์ดํฐ๋ ํ๋์ ํ์ฅ๋ ๋ฌธ์์ ์งํฉ(Extended Grapheme Clusters)์ผ๋ก ํํ๋๋ค.
Extended Grapheme Clusters
Swift์์๋ Character ์๋ฃํ์ '์ฌ๋์ด ์ฝ์ ์ ์๋ ํ๋์ ๊ธ์'๋ฅผ ๊ธฐ์ค์ผ๋ก ํ๋ค. ๊ทธ๋์ ํ๋์ ๊ธ์๊ฐ ์ฌ๋ฌ ๊ฐ์ ์ ๋์ฝ๋ ์ค์นผ๋ผ ๊ฐ์ ๊ฐ์ง ์ ์๊ณ , ์ด์ ๋ฐ๋ผ ๊ฐ ๊ธ์๋ง์ ๋ฉ๋ชจ๋ฆฌ๊ฐ ๋ค๋ฅผ ์ ์๋ค.
์์ ๊ณต์๋ฌธ์์์ ํ๋์ Character ํ์ ์ด ์ฌ๋ฌ ์ค์นผ๋ผ ๊ฐ์ ๊ฐ์ง ์ ์๋ค๋ ๊ฒ์ ํ๊ธ๋ก ์๋ฅผ ๋ค์๋ค.
let precomposed: Character = "\u{D55C}" // ํ
let decomposed: Character = "\u{1112}\u{1161}\u{11AB}" // ใ
, ใ
, ใด
// precomposed is ํ, decomposed is ํ
์์๋ฅผ ๋ณด๋ฉด ํ์ผ๋ก ํฉ์ณ์๋ ๊ธ์๋ ํ๋์ ์ ๋์ฝ๋ ์ค์นผ๋ผ ๊ฐ์ ๊ฐ๋๋ฐ ์๋๋ 3๊ฐ์ ์ ๋์ฝ๋ ์ค์นผ๋ผ ๊ฐ์ ๊ฐ๋๋ค. ํ์ง๋ง ์ค์ํ ์ ์ ๋ ๋ค ๋๊ฐ์ ํ๋์ Character๋ผ๋๊ฒ์ด๋ค.
์ด๋ฐ ์ด์ ๋๋ฌธ์ ๋ค๋ฅธ ์ธ์ด์ฒ๋ผ str[6]์ผ๋ก ์ ๊ทผํ๋ ค ํ๋ค๋ฉด, ๊ตฌ์ฒด์ ์ผ๋ก ์ด๋ ์ ๊ทผํ๋ คํ๋์ง ์๋๊ฐ ๋ช ํํ์ง ์๊ฒ ๋๋ฒ๋ฆฐ ๊ฒ์ด๋ค.
์๋๋ฉด ์ฌ์ค str[6]์์ 6์ด๋ผ๋ ์ซ์๋ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ๋ฐฐ์ด์ฒ๋ผ ์ ์ ํด์ ๊ทธ ์ค 6๋ฒ์งธ ์ธ๋ฑ์ค๋ฅผ ๋ณด๋๊ฒ์ด๊ธฐ ๋๋ฌธ์ด๋ค. Swift ์ฒ๋ผ ํ๊ธ์๋ง๋ค ์ฌ๋ฌ ๊ฐ์ ์ ๋์ฝ๋ ์ค์นผ๋ผ ๊ฐ์ ๊ฐ์ง ์ ์๋ค๋ฉด ๊ฐ ๊ธ์๋ง๋ค ๋ฉ๋ชจ๋ฆฌ๊ฐ ๋ค๋ฅด๊ธฐ ๋๋ฌธ์ ์ ํํ i ๋ฒ์งธ๋ ์๋ ๊ฒ์ด๋ค.
์ธ๋ฑ์ค๋ก ์ ๊ทผ์ ๋ชปํ๋ค๊ณ ํ์ ๋ ๋ ํ๋์ ์๋ฌธ์ ์ด ๋ ๋ค. ๋ฐ๋ก, String.Index๋ฅผ ๋ฐํํ๋
index(_:offsetBy:) ๋ฉ์๋์ด๋ค. ํด๋น ๋ฉ์๋๋ Swift๊ฐ ์ ๊ณตํ๋ ์ฒซ ๋ฒ์งธ ํ๋ผ๋ฏธํฐ๋ก๋ถํฐ offsetBy: ๋งํผ ๋จ์ด์ง ์์น๋ฅผ ๋ฐํํ๋ค.
์ฌ๊ธฐ์ "offsetBy: ๋งํผ ๋จ์ด์ง" ์ด ๋ผ๋๊ฒ์ด ๋ฌด์จ ๋ง์ธ์ง ์ค์ํ๋ค. ์๋๋ฉด ์ธ๋ฑ์ค๋ก ์กฐํํ์ง ๋ชปํ๋ค๊ณ ํ๋๋ฐ, ์ด ๋ฉ์๋๋ฅผ ์ฌ์ฉํ๋ฉด ์ด์จ๋ ์ธ๋ฑ์ค๋ก ์กฐํํ๋ '๊ฒ์ฒ๋ผ ๋ณด์ฌ์ง์ง ์๋๊ฐ'
String.Index ?
์ ๊ณต์๋ฌธ์์ ๋ฐ๋ฅด๋ฉด String ์๋ฃํ์์๋ Index ๋ผ๋ ๊ตฌ์กฐ์ฒด๋ BidirectinalCollection ์ด๋ผ๋ ํ๋กํ ์ฝ์ ์ฑํํ ๊ตฌ์กฐ์ฒด์ด๋ค.
BidirectionalCollection & RandomAccessCollection
String.Index ๊ตฌ์กฐ์ฒด๊ฐ BidirectionalCollection ์ด๋ผ๋ ํ๋กํ ์ฝ์ ์ฑํํ ๊ฒ์ ๋ฌธ์์ด์ ์ธ๋ฑ์ค ํ์ ๊ตฌ์กฐ๊ฐ ์๋ฐฉํฅ ์ํ๋ฐฉ์ ์ด๋ผ๋ ๊ฒ์ด๋ค. ๊ทธ ๋ง์ธ ์ฆ์จ, ๋ฌด์กฐ๊ฑด ์์ ์ ์, ๋ค๋ก๋ง ํ์ํ ์ ์๋ค๋ ๊ฒ์ด๋ค.
๋ณดํต์ ๋ฌธ์์ด์ Random Access ๋ฐฉ๋ฒ์ผ๋ก ์์์ ๊ฑฐ๋ฆฌ๋งํผ ๋จ์ด์ง ์์๋ฅผ O(1)์ ์๊ฐ๋ณต์ก๋๋ก ์ฐธ์กฐ ํ ์ ์๋ ์กฐํ ์ฑ๋ฅ์ ๊ฐ์ง๋ค. ํ์ง๋ง, ์ ํ์ ๊ฐ ๊ธ์๋ง๋ค ์ ์ฐํ ๋ฉ๋ชจ๋ฆฌ ํฌ๊ธฐ๋ฅผ ๊ฐ์ ธ๊ฐ ๋์ ์ด๋ฐ ์ฑ๋ฅ์ ํฌ๊ธฐํ ๊ฒ ๊ฐ๋ค.
BidirectionalCollection ํ๋กํ ์ฝ๋ก ์ธ๋ฑ์ค ์ ๊ทผ์ ๊ตฌํํจ์ผ๋ก์จ O(n)์ ์๊ฐ๋ณต์ก๋๊ฐ ํ์ํด์ก๋ค.
์ด๋ฌํ ์ด์ ๋ก, ๋ฌธ์์ด์ ์์์ ์ผ๋ก๋ถํฐ ์์์ ๊ฑฐ๋ฆฌ๋งํผ ๋จ์ด์ง ์์๋ฅผ ์ฐธ์กฐํ๊ธฐ ์ํด์๋ ์ด์ ๋จ๊ณ๋ฅผ ๋ชจ๋ ๊ฑฐ์ณ์ผ ํ๋ ๊ฒ์ด๋ค.
์ด๋ฌํ ์ ๊ทผ ๋ฐฉ์์ผ๋ก ๊ตฌํ๋์ด ๊ฐ๊ฐ์ ๋ฌธ์์ ์งํฉ๋งํผ ๋จ์ด์ง distance๋ฅผ ๊ณ์ฐํ๋ค. ๋ฌผ๋ก ์ํ๋ค๋ฉด utf-8, utf-16, unicodesScalars ๋ฐฉ์์ผ๋ก ๊ณ์ฐํ ์๋ ์๊ฒ ๋ค.
๊ฒฐ๋ก
Swift๋ ๋ค์ํ ๋ฐฉ์์ ์ธ์ด์ ํน์๋ฌธ์๋ค์ ๋์ํ๊ธฐ ์ํด ํ์ฅ๋ ๋ฌธ์์ ์งํฉ(Extended Grapheme Clusters)๋ฅผ ์ฑํํด์ ํ ๊ธ์๋น ์ ์ฐํ ๋ฉ๋ชจ๋ฆฌ ํฌ๊ธฐ๋ฅผ ๊ฐ๊ฒํ๊ณ , ์์์ ์ง์ ์ผ๋ก๋ถํฐ ๊ทธ ํฌ๊ธฐ๋งํผ ๋จ์ด์ง ์์๋ฅผ Bidirectional ํ๊ฒ ํ์ํ์ฌ ๋ฌธ์์ด์ ์์์ ์ ๊ทผํ๋ ๊ฒ์ด๋ค.
๊ด๋ จ ํ๋ก๊ทธ๋๋จธ์ค ๋ฌธ์
https://school.programmers.co.kr/learn/courses/30/lessons/181915
'๐ ์ฝ๋ฉํ ์คํธ > Swift' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[Swift] stride ( for๋ฌธ ์ผ์ ์ซ์๋งํผ ์ฆ๊ฐ ) (0) | 2023.11.14 |
---|---|
[Swift] enumerated ( ๋ฐฐ์ด์ index ๊ฐ ) (0) | 2023.11.14 |
[Swift] ReplacingOccurrences ( ๋ฌธ์์ด ์นํ ) (0) | 2023.11.02 |
[Swift] Split , Components (0) | 2023.11.02 |
[Swift] Map, Filter, Reduce (1) | 2023.11.01 |