小编典典

String.Index 如何在 Swift 中工作

all

我一直在用 Swift 3 更新我的一些旧代码和答案,但是当我接触到 Swift 字符串和索引时,理解事物一直很痛苦。

具体来说,我正在尝试以下操作:

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)

一开始这些真的让我很困惑,所以我开始玩弄它们,直到我理解它们。我在下面添加一个答案来展示它们是如何使用的。


阅读 133

收藏
2022-03-16

共1个答案

小编典典

在此处输入图像描述

以下所有示例都使用

var str = "Hello, playground"

startIndexendIndex

  • 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语句将被跳过。

为什么需要 String.Index?

对字符串使用索引会容易得多。Int您必须为每个字符串创建一个新字符串的原因String.Index是 Swift 中的字符在引擎盖下的长度并不完全相同。单个 Swift 字符可能由一个、两个甚至更多的 Unicode 代码点组成。因此,每个唯一的字符串必须计算其字符的索引。

可以将这种复杂性隐藏在 Int 索引扩展后面,但我不愿意这样做。提醒一下实际发生的事情是件好事。

2022-03-16