문자열에서 특정 문자의 인덱스를 찾으려면
1. 손으로 세는 방법과
2. range(of:) method와 distance(from:to:) method를 활용하는 방법이 있습니다.
range(of:) method와 distance(from:to:) method
var sentence = "Hello, Swift."
var s = 0
if let rangeS = sentence.range(of: "S") {
s = sentence.distance(from: sentence.startIndex, to: rangeS.lowerBound)
}
// Prints: 7
주어진 문자열 내에서 특정 문자열의 범위를 알고 싶은 경우, range(of:) method를 사용하면 문자열 안에 처음으로 일치하는 문자열의 범위를 알아낼 수 있습니다.
범위 내에 찾고자 하는 문자열이 없을 수도 있기 때문에, if문을 사용했습니다.
그리고 if문 내부에 두 인덱스 사이의 거리를 알려주는 distance(from:to:) method를 사용해서 from엔 문자열의 시작부터, 찾아낸 문자열의 범위의 시작점을 전달해 찾고자하는 문자열의 인덱스를 알아냈습니다.
공백까지 카운트해서 7번째에 문자 "S"가 있는 걸 확인할 수 있습니다.
.backwards Options
options파라미터에 .backwards를 전달해주면, 뒤에서부터 문자열을 검색하면서 처음으로 찾은 문자열의 인덱스를 리턴해줍니다.
var sentence = "Say, Hello Swift."
var s = 0
if let rangeS = sentence.range(of: "S", options: .backwards) {
s = sentence.distance(from: sentence.startIndex, to: rangeS.lowerBound)
}
print(s)
// Prints: 11
range(of:) method에서 처음을 계속 강조한 이유는, 찾고자 하는 문자열이 중복되더라도 처음으로 발견한 문자열 범위만 리턴하고 메소드 실행이 종료됩니다.
Challenge: 중복되는 문자열 인덱스 모두 찾기
var sentence = "Say, Hello Swift."
var count = -1
var indexS = [Int]()
for i in sentence {
count += 1
if i == "S" {
indexS.append(count)
}
}
print(indexS)
// prints: [0, 11]
변수 count를 선언하고, 인덱스는 0부터 시작하기 때문에 초깃값을 -1로 설정했습니다.
문자열을 나열하면서 count를 1씩 증가시켰고 전달된 문자요소가 "S"와 일치한다면, 해당 count를 indexS 배열에 추가했습니다.
이 방법은 반복상수에 문자열이 아닌, '문자만' 전달할 수 있기 때문에 다른 방법이 필요했습니다.
var originalSentence = "Say, Hello Swift."
var sentence = "Say, Hello Swift."
var indexS = [Int]()
while let range = sentence.range(of: "S", options: .caseInsensitive) {
sentence = String(sentence[sentence.index(after: range.lowerBound)...])
indexS.append(originalSentence.count-sentence.count-1)
}
print(indexS)
// prints: [0, 11]
while 반복문이 실행되는 순서는 아래와 같습니다.
range(of:) method를 사용해 문자열에 "S"가 포함되어 있다면 while 반복문 실행 ➡
"Say, Hello Swift." 에서 "ay, Hello Swift." 처럼 찾아낸 범위를 잘라내기 ➡
잘린 문자열은 sentence 변수에 다시 저장 ➡
indexS 배열에 .append method를 사용해 (원래 문자열의 길이 - 잘린 문자열 길이 - 1)로 index 순서를 맞춘 다음 요소에 추가 ➡
TIP
_range(of:) _method에 options 파라미터를 사용할 수 있습니다.
여기에 .caseInsensitive를 전달하면 배열을 비교할 때 대소문자를 구별하지 않습니다.