String.Index 如何在 Swift 中工作 [英] How does String.Index work in Swift

查看:32
本文介绍了String.Index 如何在 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"

startIndexendIndex

  • startIndex 是第一个字符的索引
  • endIndex 是最后一个字符之后的索引.
  • startIndex and endIndex

    • startIndex is the index of the first character
    • endIndex is the index after the last character.
    • 示例

      // 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 type String.IndexDistance, you can give it an 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.
      • 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 returns nil 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆