source

String은 어떻게 작동합니까?스위프트의 인덱스 작업

factcode 2023. 5. 9. 23:03
반응형

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
}

오프셋이 다음과 같았더라면777 다음에 그음에다.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

반응형