我一直在用 Swift 3 更新我的一些旧代码和答案,但是当我接触到 Swift 字符串和索引时,理解事物一直很痛苦。
具体来说,我正在尝试以下操作:
let str = "Hello, playground" let prefixRange = str.startIndex..<str.startIndex.advancedBy(5) // error
第二行给了我以下错误
“advancedBy”不可用:要将索引推进 n 步,请在生成索引的 CharacterView 实例上调用“index(_:offsetBy:)”。
我看到String有以下方法。
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
例子
// 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)
index(after: String.Index)
// 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)
index(before: String.Index)
// 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)
index(String.Index, offsetBy: String.IndexDistance)
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)
index(String.Index, offsetBy: String.IndexDistance, limitedBy: String.Index)
nil
// character if let index = str.index(str.startIndex, offsetBy: 7, limitedBy: str.endIndex) { str[index] // p }
如果偏移量是77而不是7,则该if语句将被跳过。
77
7
if
对字符串使用索引会容易得多。Int您必须为每个字符串创建一个新字符串的原因String.Index是 Swift 中的字符在引擎盖下的长度并不完全相同。单个 Swift 字符可能由一个、两个甚至更多的 Unicode 代码点组成。因此,每个唯一的字符串必须计算其字符的索引。
String.Index
可以将这种复杂性隐藏在 Int 索引扩展后面,但我不愿意这样做。提醒一下实际发生的事情是件好事。