swift - String 子字符串如何在 Swift 中工作

标签 swift string range substring

我一直在使用 Swift 3 更新我的一些旧代码和答案,但是当我使用 Swift 字符串和子字符串索引时,事情变得困惑了。

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

let str = "Hello, playground"
let prefixRange = str.startIndex..<str.startIndex.advancedBy(5)
let prefix = str.substringWithRange(prefixRange)

第二行给我以下错误

Value of type 'String' has no member 'substringWithRange'

我看到 String 现在确实有以下方法:

str.substring(to: String.Index)
str.substring(from: String.Index)
str.substring(with: Range<String.Index>)

一开始这些真的让我很困惑所以我开始玩index and range .这是子串的后续问答。我在下面添加一个答案来展示它们是如何使用的。

最佳答案

enter image description here

以下所有示例均使用

var str = "Hello, playground"

swift 4

字符串在 Swift 4 中得到了相当大的改进。当你现在从字符串中获取一些子字符串时,你得到的是 Substring 类型而不是 String。为什么是这样?字符串是 Swift 中的值类型。这意味着如果您使用一个 String 来创建一个新的,则必须将其复制过来。这有利于稳定性(没有人会在您不知情的情况下更改它)但不利于效率。

另一方面,子字符串是对其来源的原始字符串的引用。这是来自 documentation 的图片说明这一点。

无需复制,使用效率更高。但是,假设您从一百万个字符的字符串中得到了一个十个字符的子字符串。因为 Substring 正在引用 String,所以只要 Substring 存在,系统就必须保留整个 String。因此,无论何时完成对子字符串的操作,都将其转换为字符串。

let myString = String(mySubstring)

这将只复制子字符串,保存旧字符串的内存可以是 reclaimed .子字符串(作为一种类型)是短暂的。

Swift 4 的另一大改进是字符串是集合(再次)。这意味着无论您可以对 Collection 做什么,您也可以对 String 做什么(使用下标、遍历字符、过滤器等)。

以下示例展示了如何在 Swift 中获取子字符串。

获取子字符串

您可以使用下标或许多其他方法(例如,prefixsuffixsplit)从字符串中获取子字符串).不过,您仍然需要为范围使用 String.Index 而不是 Int 索引。 (如果您需要这方面的帮助,请参阅 my other answer。)

字符串的开始

您可以使用下标(注意 Swift 4 单边范围):

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

前缀:

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

后缀:

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

子字符串转换为字符串

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

let myString = String(mySubstring)

使用 Int 索引扩展?

阅读文章 Strings in Swift 3 后,我犹豫要不要使用基于 Int 的索引扩展由 Airspeed Velocity 和 Ole Begemann 提供。尽管在 Swift 4 中,字符串是集合,但 Swift 团队有意没有使用 Int 索引。它仍然是 String.Index。这与由不同数量的 Unicode 代码点组成的 Swift 字符有关。必须为每个字符串计算唯一的实际索引。

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

关于swift - String 子字符串如何在 Swift 中工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39677330/

相关文章:

java - 尝试在 java 中出现双 $$ 包机时拆分字符串

java - Json String - 如何在字符串中添加变量

python - 从文件读取时类型错误 :a bytes-like object is required, 而不是 'str'

arrays - 如何快速对 Range<Index> 的数组进行排序?

python - step_size为0的滑动窗口算法怎么写?

ios - swift 3 中 View Controller 的重复实例

ios - 排序 SwiftyJSON 结果

ios - 从 Storyboard 转换到子类

swift - 主窗口关闭时如何退出应用程序

mysql - 是否可以在 SELECT 语句中计算日期范围?