Swift 中的 String 和 Substring 如何工作

栏目: Swift · 发布时间: 5年前

内容简介:| 作者:Suragch|以下所有示例都基于下面这行代码:

| 作者:Suragch

| medium.com/@studymongo…

以下所有示例都基于下面这行代码:

var str = "Hello, playground"
复制代码

字符串与子字符串

字符串在不同的 Swift 版本中变化比较大。在 Swift 4 中,当需要从一个字符串中获取子串时,我们获取到的是 Substring 类型而不是一个 String 类型的值。为什么会这样?在 Swift 中,字符串是值类型。这意味着如果想从一个字符串中生成一个新的字符串,则需要做拷贝处理。这对于稳定性是有益的,但效率却不高。

从另一方面讲,一个 Substring 则是对其原始 String 的一个引用。它不需要做拷贝操作,所以更加高效。但是有另一个问题,假设我们要从一个很长的字符串中获取一个长度为 10 的 Substring,由于这个 Substring 会引用 String,那么只要 Substring 一直存在,String 就必须一直存在。所以,任何时候当处理完 Substring 后,需要将其转换为 String。

let myString = String(mySubstring)
复制代码

这样只会拷贝子串,而原来的字符串可以被正确地回收。Substring 作为一种类型,本身即表示临时存在的。

在 Swift 4 另一个大的改进是字符串又成为集合了。这意味着在集合上的所有操作,也可以应用在字符串中(如下标、迭代字符、过滤等)。

String.Index

在我们更多地了解子字符串之前,了解 String 索引如何作用于字符串中的字符会有很大的帮助。

startIndex 和 endIndex

startIndex
endIndex

示例

var str = "Hello, playground"
// 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 的单侧范围( one-side ranges )功能,可将范围简化为以下形式之一。

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 值来指定索引范围。

字符串的起始值

我们可以使用下标(注意 Swift 4 的单侧范围):

let index = str.index(str.startIndex, offsetBy: 5)
let mySubstring = str[..<index] // Hello
复制代码

或者 prefix

let index = str.index(str.startIndex, offsetBy: 5)
let mySubstring = str.prefix(upTo: index) // Hello
复制代码

或者更简单的方式:

let mySubstring = str.prefix(5) // Hello
复制代码

字符串的结束值

使用下标:

let index = str.index(str.endIndex, offsetBy: -10)
let mySubstring = str[index...] // playground
复制代码

或者 suffix

let index = str.index(str.endIndex, offsetBy: -10)
let mySubstring = str.suffix(from: index) // playground
复制代码

或者更简单的方式:

let mySubstring = str.suffix(10) // playground
复制代码

请注意,当使用 suffix(from: index) 时,我必须使用 -10 从最后算起。 当只使用 suffix(x) 时,则不需要,后缀只占用字符串的最后 x 个字符。

字符串的范围

我们再次使用下标:

let start = str.index(str.startIndex, offsetBy: 7)
let end = str.index(str.endIndex, offsetBy: -6)
let range = start..<end
let mySubstring = str[range]  // play
复制代码

将 Substring 转换为 String

不要忘记,当您准备保存子字符串时,应将其转换为 String ,以便清除旧字符串的内存。

let myString = String(mySubstring)
复制代码

使用 Int 索引扩展

对字符串使用 Int 索引要容易得多。实际上,通过使用基于 Int 的扩展,可以隐藏 String 索引的复杂性。然而,在读完 Airspeed Velocity 和 Ole Begemann 的文章 Strings in Swift 3 后,我犹豫不决。此外,Swift 团队故意没有使用 Int 索引,而仍然使用 String.Index 。原因是 Swift 中的 Character 在底层的长度并不完全相同。单个 Swift 字符可能由一个、两个甚至更多 Unicode 组成。 因此,每个唯一的 String 必须计算其 Character 的索引。

不得不说,我希望 Swift 团队找到一种方法来在将来抽象出 String.Index 。但在此之前,我选择使用他们的 API。它帮助我记住 String 操作不仅仅是简单的 Int 索引查找。


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

数据结构与算法分析

数据结构与算法分析

韦斯 (Mark Allen Weiss) / 机械工业出版社 / 2013-2-1 / 79.00元

本书是国外数据结构与算法分析方面的经典教材,使用卓越的Java编程语言作为实现工具讨论了数据结构(组织大量数据的方法)和算法分析(对算法运行时间的估计)。 随着计算机速度的不断增加和功能的日益强大,人们对有效编程和算法分析的要求也不断增长。本书将算法分析与最有效率的Java程序的开发有机地结合起来,深入分析每种算法,并细致讲解精心构造程序的方法,内容全面、缜密严格。 第3版的主要更新如......一起来看看 《数据结构与算法分析》 这本书的介绍吧!

RGB转16进制工具
RGB转16进制工具

RGB HEX 互转工具

UNIX 时间戳转换
UNIX 时间戳转换

UNIX 时间戳转换