[swift] Swift 프로그래밍 언어에서 문자열의 n 번째 문자 가져 오기

문자열의 n 번째 문자를 얻으려면 어떻게해야합니까? []행운이없이 bracket ( ) 접근 자를 시도했습니다 .

var string = "Hello, world!"

var firstChar = string[0] // Throws error

오류 : ‘아래 첨자’를 사용할 수 없습니다 : Int로 문자열을 첨자 할 수 없습니다. 설명서 주석을 참조하십시오.



답변

주의 : Swift 4 및 Swift 5의 올바른 구현에 대해서는 Leo Dabus의 답변 을 참조하십시오 .

스위프트 4 이상

Substring유형은 원본 문자열과 스토리지를 공유하여 하위 문자열을 더 빠르고 효율적으로 만들기 위해 Swift 4에 도입되었으므로 하위 스크립트 함수가 반환해야합니다.

여기서 사용해보십시오

extension StringProtocol {
    subscript(offset: Int) -> Character { self[index(startIndex, offsetBy: offset)] }
    subscript(range: Range<Int>) -> SubSequence {
        let startIndex = index(self.startIndex, offsetBy: range.lowerBound)
        return self[startIndex..<index(startIndex, offsetBy: range.count)]
    }
    subscript(range: ClosedRange<Int>) -> SubSequence {
        let startIndex = index(self.startIndex, offsetBy: range.lowerBound)
        return self[startIndex..<index(startIndex, offsetBy: range.count)]
    }
    subscript(range: PartialRangeFrom<Int>) -> SubSequence { self[index(startIndex, offsetBy: range.lowerBound)...] }
    subscript(range: PartialRangeThrough<Int>) -> SubSequence { self[...index(startIndex, offsetBy: range.upperBound)] }
    subscript(range: PartialRangeUpTo<Int>) -> SubSequence { self[..<index(startIndex, offsetBy: range.upperBound)] }
}

을 변환하려면 SubstringString, 당신은 간단하게 할 수 String(string[0..2])있지만, 당신은 당신이하려는 경우 주변 하위 문자열 유지하는 것을해야한다. 그렇지 않으면을 유지하는 것이 더 효율적 Substring입니다.

누군가이 두 확장을 하나로 병합하는 좋은 방법을 알아낼 수 있다면 좋을 것입니다. 방법이 존재하지 StringProtocol
않기 때문에 성공하지 않고 확장 을 시도 index했습니다.
참고 :이 답변은 이미 편집되었으며 올바르게 구현되어 이제 하위 문자열에서도 작동합니다. StringProtocol 유형을 첨자화할 때 충돌을 피하려면 유효한 범위를 사용해야합니다. 범위를 벗어난 값으로 충돌하지 않는 범위를 가진 첨자를 위해이 구현을 사용할 수 있습니다


왜 이것이 내장되어 있지 않습니까?

오류 메시지에 “토론을위한 설명서 주석 참조”가 표시 됩니다. Apple은 UnavailableStringAPIs.swift 파일에 다음 설명을 제공합니다 .

정수로 첨자 문자열을 사용할 수 없습니다.

i문자열의 문자 “개념은 라이브러리 및 시스템 구성 요소에 따라 다르게 해석됩니다. 사용 사례 및 관련 API에 따라 올바른 해석을 선택해야하므로 String
정수로 첨자를 사용할 수 없습니다.

Swift는 문자열 안에 저장된 문자 데이터에 액세스하는 여러 가지 방법을 제공합니다.

  • String.utf8문자열에서 UTF-8 코드 단위의 모음입니다. 문자열을 UTF-8로 변환 할 때이 API를 사용하십시오. 대부분의 POSIX API는 UTF-8 코드 단위로 문자열을 처리합니다.

  • String.utf16문자열로 된 UTF-16 코드 단위의 모음입니다. 대부분의 Cocoa 및 Cocoa touch API는 문자열을 UTF-16 코드 단위로 처리합니다. 예를 들어, UTF-16 코드 단위로 하위 문자열 오프셋 및 길이 NSRange와 함께 사용 NSAttributedString
    NSRegularExpression저장 되는 인스턴스입니다
    .

  • String.unicodeScalars유니 코드 스칼라의 모음입니다. 문자 데이터의 저수준 조작을 수행 할 때이 API를 사용하십시오.

  • String.characters 사용자가 인식 한 문자의 근사치 인 확장 된 grapheme 클러스터 모음입니다.

사람이 읽을 수있는 텍스트가 포함 된 문자열을 처리 할 때는 문자 별 처리를 최대한 피해야합니다. 대신에 고급 로케일 구분 유니 코드 알고리즘을 사용하십시오 (예
String.localizedStandardCompare():
String.localizedLowercaseString,
String.localizedStandardRangeOfString()등).


답변

스위프트 5.2

let str = "abcdef"
str[1 ..< 3] // returns "bc"
str[5] // returns "f"
str[80] // returns ""
str.substring(fromIndex: 3) // returns "def"
str.substring(toIndex: str.length - 2) // returns "abcd"

이 문자열 확장을 프로젝트에 추가해야합니다 (완전히 테스트 됨).

extension String {

    var length: Int {
        return count
    }

    subscript (i: Int) -> String {
        return self[i ..< i + 1]
    }

    func substring(fromIndex: Int) -> String {
        return self[min(fromIndex, length) ..< length]
    }

    func substring(toIndex: Int) -> String {
        return self[0 ..< max(0, toIndex)]
    }

    subscript (r: Range<Int>) -> String {
        let range = Range(uncheckedBounds: (lower: max(0, min(length, r.lowerBound)),
                                            upper: min(length, max(0, r.upperBound))))
        let start = index(startIndex, offsetBy: range.lowerBound)
        let end = index(start, offsetBy: range.upperBound - range.lowerBound)
        return String(self[start ..< end])
    }
}

Swift가 항상이 문제에 대한 해결책을 항상 가지고 있었지만 (아래에 제공 한 String 확장명 없음) 여전히 확장명을 사용하는 것이 좋습니다 . 왜? String의 구문이 거의 모든 릴리스에서 변경되는 초기 버전의 Swift에서 수십 시간의 고통스러운 마이그레이션을 절약했기 때문에 전체 프로젝트를 리팩토링하는 대신 확장 구현을 업데이트하기 만하면됩니다. 선택하십시오.

let str = "Hello, world!"
let index = str.index(str.startIndex, offsetBy: 4)
str[index] // returns Character 'o'

let endIndex = str.index(str.endIndex, offsetBy:-2)
str[index ..< endIndex] // returns String "o, worl"

String(str.suffix(from: index)) // returns String "o, world!"
String(str.prefix(upTo: index)) // returns String "Hell"


답변

방금이 깔끔한 해결 방법을 생각해 냈습니다.

var firstChar = Array(string)[0]


답변

정수만 사용하여 인덱싱하지 않고을 사용 String.Index합니다. 대부분 선형 복잡성. 범위를 작성 String.Index하고이를 사용하여 하위 문자열을 얻을 수도 있습니다 .

스위프트 3.0

let firstChar = someString[someString.startIndex]
let lastChar = someString[someString.index(before: someString.endIndex)]
let charAtIndex = someString[someString.index(someString.startIndex, offsetBy: 10)]

let range = someString.startIndex..<someString.index(someString.startIndex, offsetBy: 10)
let substring = someString[range]

스위프트 2.x

let firstChar = someString[someString.startIndex]
let lastChar = someString[someString.endIndex.predecessor()]
let charAtIndex = someString[someString.startIndex.advanceBy(10)]

let range = someString.startIndex..<someString.startIndex.advanceBy(10)
let subtring = someString[range]

한 문자열에서 다른 문자열로 생성 된 인덱스 (또는 범위)는 사용할 수 없습니다.

let index10 = someString.startIndex.advanceBy(10)

//will compile
//sometimes it will work but sometimes it will crash or result in undefined behaviour
let charFromAnotherString = anotherString[index10]


답변

Xcode 11 • 스위프트 5.1

StringProtocol을 확장하여 아래 첨자도 아래 첨자를 사용할 수 있습니다.

extension StringProtocol {
    subscript(_ offset: Int)                     -> Element     { self[index(startIndex, offsetBy: offset)] }
    subscript(_ range: Range<Int>)               -> SubSequence { prefix(range.lowerBound+range.count).suffix(range.count) }
    subscript(_ range: ClosedRange<Int>)         -> SubSequence { prefix(range.lowerBound+range.count).suffix(range.count) }
    subscript(_ range: PartialRangeThrough<Int>) -> SubSequence { prefix(range.upperBound.advanced(by: 1)) }
    subscript(_ range: PartialRangeUpTo<Int>)    -> SubSequence { prefix(range.upperBound) }
    subscript(_ range: PartialRangeFrom<Int>)    -> SubSequence { suffix(Swift.max(0, count-range.lowerBound)) }
}

extension LosslessStringConvertible {
    var string: String { .init(self) }
}

extension BidirectionalCollection {
    subscript(safe offset: Int) -> Element? {
        guard !isEmpty, let i = index(startIndex, offsetBy: offset, limitedBy: index(before: endIndex)) else { return nil }
        return self[i]
    }
}

테스팅

let test = "Hello USA ??!!! Hello Brazil ??!!!"
test[safe: 10]   // "??"
test[11]   // "!"
test[10...]   // "??!!! Hello Brazil ??!!!"
test[10..<12]   // "??!"
test[10...12]   // "??!!"
test[...10]   // "Hello USA ??"
test[..<10]   // "Hello USA "
test.first   // "H"
test.last    // "!"

// Subscripting the Substring
 test[...][...3]  // "Hell"

// Note that they all return a Substring of the original String.
// To create a new String from a substring
test[10...].string  // "??!!! Hello Brazil ??!!!"


답변

스위프트 4

let str = "My String"

인덱스의 문자열

let index = str.index(str.startIndex, offsetBy: 3)
String(str[index])    // "S"

부분 문자열

let startIndex = str.index(str.startIndex, offsetBy: 3)
let endIndex = str.index(str.startIndex, offsetBy: 7)
String(str[startIndex...endIndex])     // "Strin"

첫 n 자

let startIndex = str.index(str.startIndex, offsetBy: 3)
String(str[..<startIndex])    // "My "

마지막 n 자

let startIndex = str.index(str.startIndex, offsetBy: 3)
String(str[startIndex...])    // "String"

스위프트 2와 3

str = "My String"

** 지수 문자열 **

스위프트 2

let charAtIndex = String(str[str.startIndex.advancedBy(3)])  // charAtIndex = "S"

스위프트 3

str[str.index(str.startIndex, offsetBy: 3)]

Index to Index to SubString

스위프트 2

let subStr = str[str.startIndex.advancedBy(3)...str.startIndex.advancedBy(7)] // subStr = "Strin"

스위프트 3

str[str.index(str.startIndex, offsetBy: 3)...str.index(str.startIndex, offsetBy: 7)]

첫 n 자

let first2Chars = String(str.characters.prefix(2)) // first2Chars = "My"

마지막 n 자

let last3Chars = String(str.characters.suffix(3)) // last3Chars = "ing"


답변

Xcode 7 GM Seed의 Swift 2.0

var text = "Hello, world!"

let firstChar = text[text.startIndex.advancedBy(0)] // "H"

n 번째 문자의 경우 0을 n-1로 바꾸십시오.

편집 : 스위프트 3.0

text[text.index(text.startIndex, offsetBy: 0)]

nb 문자열에서 특정 문자를 잡는 간단한 방법이 있습니다

예 : let firstChar = text.characters.first