String.Index 如何在 Swift 中工作 [英] How does String.Index work in Swift
问题描述
我一直在用 Swift 3 更新我的一些旧代码和答案,但是当我开始使用 Swift 字符串和索引时,理解起来很痛苦.
I've been updating some of my old code and answers with Swift 3 but when I got to Swift Strings and Indexing it has been a pain to understand things.
具体来说,我正在尝试以下操作:
Specifically I was trying the following:
let str = "Hello, playground"
let prefixRange = str.startIndex..<str.startIndex.advancedBy(5) // error
第二行给我以下错误
'advancedBy' 不可用:要将索引推进 n 步,请在生成索引的 CharacterView 实例上调用 'index(_:offsetBy:)'.
'advancedBy' is unavailable: To advance an index by n steps call 'index(_:offsetBy:)' on the CharacterView instance that produced the index.
我看到 String
有以下方法.
I see that String
has the following methods.
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)
一开始这些真的让我很困惑,所以我开始玩弄它们直到我理解它们.我在下面添加了一个答案来展示它们是如何使用的.
These were really confusing me at first so I started playing around with them until I understood them. I am adding an answer below to show how they are used.
推荐答案
以下所有示例均使用
var str = "Hello, playground"
startIndex
和 endIndex
startIndex
是第一个字符的索引endIndex
是最后一个字符之后的索引.startIndex
is the index of the first characterendIndex
is the index after the last character.
startIndex
and 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 的单边范围,范围可以简化为以下形式之一.
With Swift 4's one-sided ranges, the range can be simplified to one of the following forms.
let range = str.startIndex...
let range = ..<str.endIndex
为了清楚起见,我将在以下示例中使用完整形式,但为了可读性,您可能希望在代码中使用单边范围.
I will use the full form in the follow examples for the sake of clarity, but for the sake of readability, you will probably want to use the one-sided ranges in your code.
如:index(after: String.Index)
after
指的是直接在给定索引之后的字符的索引.
after
refers to the index of the character directly after the given 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"
之前
如:index(before: String.Index)
before
指的是直接在给定索引之前的字符的索引.
before
refers to the index of the character directly before the given 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)
offsetBy
值可以是正数或负数,并从给定的索引开始.虽然它是String.IndexDistance
类型,但你可以给它一个Int
.
- The
offsetBy
value can be positive or negative and starts from the given index. Although it is of the typeString.IndexDistance
, you can give it anInt
.
示例
// 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
.
- The
limitedBy
is useful for making sure that the offset does not cause the index to go out of bounds. It is a bounding index. Since it is possible for the offset to exceed the limit, this method returns an Optional. It returnsnil
if the index is out of bounds.
示例
// character
if let index = str.index(str.startIndex, offsetBy: 7, limitedBy: str.endIndex) {
str[index] // p
}
如果偏移量是 77
而不是 7
,则 if
语句将被跳过.
If the offset had been 77
instead of 7
, then the if
statement would have been skipped.
为字符串使用 Int
索引会容易得多.您必须为每个字符串创建一个新的 String.Index
的原因是 Swift 中的字符在引擎盖下的长度并不完全相同.单个 Swift 字符可能由一个、两个甚至更多 Unicode 代码点组成.因此,每个唯一的字符串都必须计算其字符的索引.
It would be much easier to use an Int
index for Strings. The reason that you have to create a new String.Index
for every String is that Characters in Swift are not all the same length under the hood. A single Swift Character might be composed of one, two, or even more Unicode code points. Thus each unique String must calculate the indexes of its Characters.
可以将这种复杂性隐藏在 Int 索引扩展之后,但我不愿意这样做.提醒自己实际发生的事情是件好事.
It is possible to hide this complexity behind an Int index extension, but I am reluctant to do so. It is good to be reminded of what is actually happening.
这篇关于String.Index 如何在 Swift 中工作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!