在Swift編程語言中獲取字符串的第n個字符

本文翻譯自:Get nth character of a string in Swift programming language

How can I get the nth character of a string? 如何獲得字符串的第n個字符? I tried bracket( [] ) accessor with no luck. 我試過沒有運氣的方括號( [] )訪問器。

var string = "Hello, world!"

var firstChar = string[0] // Throws error

ERROR: 'subscript' is unavailable: cannot subscript String with an Int, see the documentation comment for discussion 錯誤:“下標”不可用:無法對帶Int的字符串進行下標,請參見文檔註釋以進行討論


#1樓

參考:https://stackoom.com/question/1d5eu/在Swift編程語言中獲取字符串的第n個字符


#2樓

The swift string class does not provide the ability to get a character at a specific index because of its native support for UTF characters. swift字符串類不提供在特定索引處獲取字符的功能,因爲其對UTF字符的本機支持。 The variable length of a UTF character in memory makes jumping directly to a character impossible. UTF字符在內存中的可變長度使得無法直接跳轉到字符。 That means you have to manually loop over the string each time. 這意味着您每次都必須手動遍歷字符串。

You can extend String to provide a method that will loop through the characters until your desired index 您可以擴展String以提供一種方法,該方法將循環遍歷字符,直到所需的索引爲止

extension String {
    func characterAtIndex(index: Int) -> Character? {
        var cur = 0
        for char in self {
            if cur == index {
                return char
            }
            cur++
        }
        return nil
    }
}

myString.characterAtIndex(0)!

#3樓

Swift's String type does not provide a characterAtIndex method because there are several ways a Unicode string could be encoded. Swift的String類型不提供characterAtIndex方法,因爲可以通過多種方式對Unicode字符串進行編碼。 Are you going with UTF8, UTF16, or something else? 您要使用UTF8,UTF16還是其他?

You can access the CodeUnit collections by retrieving the String.utf8 and String.utf16 properties. 您可以通過檢索String.utf8String.utf16屬性來訪問CodeUnit集合。 You can also access the UnicodeScalar collection by retrieving the String.unicodeScalars property. 您還可以通過檢索String.unicodeScalars屬性來訪問UnicodeScalar集合。

In the spirit of NSString 's implementation, I'm returning a unichar type. 本着NSString實現的精神,我返回了一個unichar類型。

extension String
{
    func characterAtIndex(index:Int) -> unichar
    {
        return self.utf16[index]
    }

    // Allows us to use String[index] notation
    subscript(index:Int) -> unichar
    {
        return characterAtIndex(index)
    }
}

let text = "Hello Swift!"
let firstChar = text[0]

#4樓

Attention: Please see Leo Dabus' answer for a proper implementation for Swift 4. 注意:請參閱Leo Dabus的答案以獲取對Swift 4的正確實現。

Swift 4 斯威夫特4

The Substring type was introduced in Swift 4 to make substrings faster and more efficient by sharing storage with the original string, so that's what the subscript functions should return. 在Swift 4中引入了Substring類型,以通過與原始字符串共享存儲來使子字符串更快,更有效,這就是下標函數應該返回的內容。

Try it out here 在這裏嘗試

extension String {
  subscript (i: Int) -> Character {
    return self[index(startIndex, offsetBy: i)]
  }
  subscript (bounds: CountableRange<Int>) -> Substring {
    let start = index(startIndex, offsetBy: bounds.lowerBound)
    let end = index(startIndex, offsetBy: bounds.upperBound)
    return self[start ..< end]
  }
  subscript (bounds: CountableClosedRange<Int>) -> Substring {
    let start = index(startIndex, offsetBy: bounds.lowerBound)
    let end = index(startIndex, offsetBy: bounds.upperBound)
    return self[start ... end]
  }
  subscript (bounds: CountablePartialRangeFrom<Int>) -> Substring {
    let start = index(startIndex, offsetBy: bounds.lowerBound)
    let end = index(endIndex, offsetBy: -1)
    return self[start ... end]
  }
  subscript (bounds: PartialRangeThrough<Int>) -> Substring {
    let end = index(startIndex, offsetBy: bounds.upperBound)
    return self[startIndex ... end]
  }
  subscript (bounds: PartialRangeUpTo<Int>) -> Substring {
    let end = index(startIndex, offsetBy: bounds.upperBound)
    return self[startIndex ..< end]
  }
}
extension Substring {
  subscript (i: Int) -> Character {
    return self[index(startIndex, offsetBy: i)]
  }
  subscript (bounds: CountableRange<Int>) -> Substring {
    let start = index(startIndex, offsetBy: bounds.lowerBound)
    let end = index(startIndex, offsetBy: bounds.upperBound)
    return self[start ..< end]
  }
  subscript (bounds: CountableClosedRange<Int>) -> Substring {
    let start = index(startIndex, offsetBy: bounds.lowerBound)
    let end = index(startIndex, offsetBy: bounds.upperBound)
    return self[start ... end]
  }
  subscript (bounds: CountablePartialRangeFrom<Int>) -> Substring {
    let start = index(startIndex, offsetBy: bounds.lowerBound)
    let end = index(endIndex, offsetBy: -1)
    return self[start ... end]
  }
  subscript (bounds: PartialRangeThrough<Int>) -> Substring {
    let end = index(startIndex, offsetBy: bounds.upperBound)
    return self[startIndex ... end]
  }
  subscript (bounds: PartialRangeUpTo<Int>) -> Substring {
    let end = index(startIndex, offsetBy: bounds.upperBound)
    return self[startIndex ..< end]
  }
}

To convert the Substring into a String , you can simply do String(string[0..2]) , but you should only do that if you plan to keep the substring around. 要將Substring轉換爲String ,您可以簡單地執行String(string[0..2]) ,但是只有在計劃保留子字符串的情況下才應該這樣做。 Otherwise, it's more efficient to keep it a Substring . 否則,將其保留爲Substring更爲有效。

It would be great if someone could figure out a good way to merge these two extensions into one. 如果有人能找到一種很好的方法將這兩個擴展合併爲一個,那將是很好的。 I tried extending StringProtocol without success, because the index method does not exist there. 我嘗試擴展StringProtocol失敗,因爲那裏沒有index方法。

Swift 3: 斯威夫特3:

extension String {
  subscript (i: Int) -> Character {
    return self[index(startIndex, offsetBy: i)]
  }
  subscript (i: Int) -> String {
    return String(self[i] as Character)
  }
  subscript (r: Range<Int>) -> String {
    let start = index(startIndex, offsetBy: r.lowerBound)
    let end = index(startIndex, offsetBy: r.upperBound)
    return self[Range(start ..< end)]
  }
}

Why is this not built-in? 爲什麼這不是內置的?

Apple provides the following explanation ( found here ): 蘋果提供了以下說明(可在此處找到 ):

Subscripting strings with integers is not available. 用整數下標字符串不可用。

The concept of "the i th character in a string" has different interpretations in different libraries and system components. “字符串中的第i個字符”的概念在不同的庫和系統組件中具有不同的解釋。 The correct interpretation should be selected according to the use case and the APIs involved, so String cannot be subscripted with an integer. 應該根據用例和所涉及的API選擇正確的解釋,因此String不能用整數下標。

Swift provides several different ways to access the character data stored inside strings. Swift提供了幾種不同的方式來訪問存儲在字符串中的字符數據。

  • String.utf8 is a collection of UTF-8 code units in the string. String.utf8是字符串中UTF-8代碼單元的集合。 Use this API when converting the string to UTF-8. 將字符串轉換爲UTF-8時,請使用此API。 Most POSIX APIs process strings in terms of UTF-8 code units. 大多數POSIX API按照UTF-8代碼單位處理字符串。

  • String.utf16 is a collection of UTF-16 code units in string. String.utf16是字符串中UTF-16代碼單元的集合。 Most Cocoa and Cocoa touch APIs process strings in terms of UTF-16 code units. 大多數Cocoa和Cocoa touch API按照UTF-16代碼單位處理字符串。 For example, instances of NSRange used with NSAttributedString and NSRegularExpression store substring offsets and lengths in terms of UTF-16 code units. 例如,與NSAttributedStringNSRegularExpression NSRange使用的NSAttributedString實例以UTF-16代碼單位存儲子字符串偏移量和長度。

  • String.unicodeScalars is a collection of Unicode scalars. String.unicodeScalars是Unicode標量的集合。 Use this API when you are performing low-level manipulation of character data. 在執行字符數據的低級操作時,請使用此API。

  • String.characters is a collection of extended grapheme clusters, which are an approximation of user-perceived characters. String.characters是擴展的字素簇的集合,這些簇是用戶感知的字符的近似值。

Note that when processing strings that contain human-readable text, character-by-character processing should be avoided to the largest extent possible. 請注意,在處理包含人類可讀文本的字符串時,應儘可能避免逐字符處理。 Use high-level locale-sensitive Unicode algorithms instead, for example, String.localizedStandardCompare() , String.localizedLowercaseString , String.localizedStandardRangeOfString() etc. 請改用高級區域設置敏感的Unicode算法,例如String.localizedStandardCompare()String.localizedLowercaseStringString.localizedStandardRangeOfString()等。


#5樓

我只是想出了這個巧妙的解決方法

var firstChar = Array(string)[0]

#6樓

No indexing using integers, only using String.Index . 不使用整數索引,僅使用String.Index Mostly with linear complexity. 通常具有線性複雜度。 You can also create ranges from String.Index and get substrings using them. 您還可以從String.Index創建範圍並使用它們獲取子字符串。

Swift 3.0 斯威夫特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]

Swift 2.x 斯威夫特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]

Note that you can't ever use an index (or range) created from one string to another string 請注意,您永遠無法使用從一個字符串創建到另一個字符串的索引(或範圍)

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]
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章