String은 어떻게 작동합니까?스위프트의 인덱스 작업
Swift 3으로 이전 코드와 답변을 업데이트해 왔지만 Swift Strings and Indexing에 도달했을 때는 이해하기가 어려웠습니다.
특히 저는 다음을 시도하고 있었습니다.
let str = "Hello, playground"
let prefixRange = str.startIndex..<str.startIndex.advancedBy(5) // error
두 번째 줄이 나에게 다음과 같은 오류를 주고 있던 곳.
'advancedBy'를 사용할 수 없습니다.인덱스를 n단계 진행하려면 인덱스를 생성한 CharacterView 인스턴스에서 'index(_:offsetBy:)'를 호출합니다.
나도 그것을 알아.String
에는 다음과 같은 메서드가 있습니다.
str.index(after: String.Index)
str.index(before: String.Index)
str.index(String.Index, offsetBy: String.IndexDistance)
str.index(String.Index, offsetBy: String.IndexDistance, limitedBy: String.Index)
이것들은 처음에는 정말 저를 혼란스럽게 했기 때문에 저는 그것들을 이해할 때까지 그것들을 가지고 놀기 시작했습니다.그들이 어떻게 사용되는지 보여주기 위해 아래에 답변을 추가합니다.
다음의 모든 예는 다음을 사용합니다.
var str = "Hello, playground"
startIndex
그리고.endIndex
startIndex
는 첫 의 입니다.endIndex
마지막 문자 뒤의 인덱스입니다.
예
// character
str[str.startIndex] // H
str[str.endIndex] // error: after last character
// range
let range = str.startIndex..<str.endIndex
str[range] // "Hello, playground"
Swift 4의 단측 범위를 사용하면 범위를 다음 형식 중 하나로 단순화할 수 있습니다.
let range = str.startIndex...
let range = ..<str.endIndex
명확성을 위해 다음 예제의 전체 양식을 사용하겠지만, 가독성을 위해 코드의 단측 범위를 사용하는 것이 좋습니다.
after
다음과 같이:index(after: String.Index)
after
지정된 인덱스 바로 뒤에 있는 문자의 인덱스를 나타냅니다.
예
// character
let index = str.index(after: str.startIndex)
str[index] // "e"
// range
let range = str.index(after: str.startIndex)..<str.endIndex
str[range] // "ello, playground"
before
다음과 같이:index(before: String.Index)
before
지정된 인덱스 바로 앞에 있는 문자의 인덱스를 나타냅니다.
예
// character
let index = str.index(before: str.endIndex)
str[index] // d
// range
let range = str.startIndex..<str.index(before: str.endIndex)
str[range] // Hello, playgroun
offsetBy
다음과 같이:index(String.Index, offsetBy: String.IndexDistance)
- 그
offsetBy
값은 양수 또는 음수일 수 있으며 지정된 인덱스에서 시작합니다.그런 종류의 것이지만,String.IndexDistance
당신은 그것을 줄 수 있습니다.Int
.
예
// character
let index = str.index(str.startIndex, offsetBy: 7)
str[index] // p
// range
let start = str.index(str.startIndex, offsetBy: 7)
let end = str.index(str.endIndex, offsetBy: -6)
let range = start..<end
str[range] // play
limitedBy
다음과 같이:index(String.Index, offsetBy: String.IndexDistance, limitedBy: String.Index)
- 그
limitedBy
오프셋으로 인해 인덱스가 범위를 벗어나지 않도록 하는 데 유용합니다.이것은 경계 지수입니다.오프셋이 한계를 초과할 수 있으므로 이 메서드는 Optional(선택 사항)을 반환합니다.를 합니다.nil
인덱스가 범위를 벗어나는 경우
예
// character
if let index = str.index(str.startIndex, offsetBy: 7, limitedBy: str.endIndex) {
str[index] // p
}
오프셋이 다음과 같았더라면77
에 7
다음에 그음에다.if
문을 건너뛸 수 있습니다.
문자열은 왜입니까?색인이 필요합니까?
사용하는 것이 훨씬 더 쉬울 것입니다.Int
문자열에 대한 인덱스입니다.를 는 이는하입니다.String.Index
모든 문자열은 스위프트의 문자가 후드 아래에서 모두 같은 길이가 아니라는 것을 의미합니다.단일 스위프트 문자는 하나, 둘 또는 그 이상의 유니코드 코드 포인트로 구성될 수 있습니다.따라서 각 고유 문자열은 해당 문자의 인덱스를 계산해야 합니다.
Int 인덱스 확장 뒤에 이 복잡성을 숨길 수 있지만, 저는 그렇게 하기를 꺼립니다.실제로 일어나고 있는 일을 상기하는 것은 좋은 일입니다.
저는 이 질문과 모든 정보에 감사드립니다.String에 관한 질문과 답변을 생각해 둔 것이 있습니다.색인.
인덱스 함수의 정의를 살펴보면 string.index(startIndex, offsetBy: 1)가 O(n) 속도이기 때문에 문자열 내부의 하위 문자열(또는 문자)에 액세스할 수 있는 O(1) 방법이 있는지 확인하려고 합니다.물론 다음과 같은 작업을 수행할 수 있습니다.
let characterArray = Array(string)
그런 다음 characterArray의 모든 위치에 액세스합니다. 그러나 이것의 공간 복잡성은n
문자열의 길이, O(n)이므로 공간 낭비입니다.
스위프트를 보고 있었어요Xcode로 된 문자열 문서와 동결된 공공 구조가 있습니다.Index
다음과 같이 초기화할 수 있습니다.
let index = String.Index(encodedOffset: 0)
그런 다음 String 개체의 인덱스에 액세스하거나 다음과 같이 인쇄합니다.
print(string[index])
주의: 범위를 벗어나지 않도록 주의하십시오.
이것은 효과적이고 훌륭하지만, 이러한 방식으로 실행하면 실행 시간과 공간이 얼마나 복잡할까요.좀 나아졌습니까?
func change(string: inout String) {
var character: Character = .normal
enum Character {
case space
case newLine
case normal
}
for i in stride(from: string.count - 1, through: 0, by: -1) {
// first get index
let index: String.Index?
if i != 0 {
index = string.index(after: string.index(string.startIndex, offsetBy: i - 1))
} else {
index = string.startIndex
}
if string[index!] == "\n" {
if character != .normal {
if character == .newLine {
string.remove(at: index!)
} else if character == .space {
let number = string.index(after: string.index(string.startIndex, offsetBy: i))
if string[number] == " " {
string.remove(at: number)
}
character = .newLine
}
} else {
character = .newLine
}
} else if string[index!] == " " {
if character != .normal {
string.remove(at: index!)
} else {
character = .space
}
} else {
character = .normal
}
}
// startIndex
guard string.count > 0 else { return }
if string[string.startIndex] == "\n" || string[string.startIndex] == " " {
string.remove(at: string.startIndex)
}
// endIndex - here is a little more complicated!
guard string.count > 0 else { return }
let index = string.index(before: string.endIndex)
if string[index] == "\n" || string[index] == " " {
string.remove(at: index)
}
}
테이블 뷰 컨트롤러 내에 UITextView를 만듭니다.저는 textViewDidChange 함수를 사용한 다음 반환 키 입력을 확인했습니다.그런 다음 반환 키 입력이 탐지되면 반환 키 입력을 삭제하고 키보드를 해제합니다.
func textViewDidChange(_ textView: UITextView) {
tableView.beginUpdates()
if textView.text.contains("\n"){
textView.text.remove(at: textView.text.index(before: textView.text.endIndex))
textView.resignFirstResponder()
}
tableView.endUpdates()
}
언급URL : https://stackoverflow.com/questions/39676939/how-does-string-index-work-in-swift
'source' 카테고리의 다른 글
일반 목록/에뮬레이터를 데이터 테이블로 변환하시겠습니까? (0) | 2023.05.09 |
---|---|
Git 저장소에서 삭제된 파일을 모두 나열하려면 어떻게 해야 합니까? (0) | 2023.05.09 |
메이븐 프로젝트 업데이트 오류 해결 방법지원되지 않는 IClasspathEntrykind=4? (0) | 2023.05.09 |
Github 사용 권한 거부: SSH add 에이전트에 ID가 없습니다. (0) | 2023.05.09 |
WPF 검증에서 ValidateOnNotifyDataErrors 및 ValidateOnDataErrors와 NotifyOnValidationErrors의 차이점은 무엇입니까? (0) | 2023.05.09 |