我一直在用Swift 3更新我的一些旧代码和答案,但当我使用Swift字符串和子字符串进行索引时,事情变得很混乱.

具体来说,我try 了以下几点:

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

第二行给了我以下错误

"String"类型的值没有成员"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中的值类型.这意味着如果你使用一个字符串来创建一个新的字符串,那么它必须被复制过来.这有利于 solidity (在你不知情的情况下,没有人会改变它),但对效率不利.

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

无需复制,因此使用效率更高.然而,假设你从一个百万字符的字符串中得到了一个十个字符的子字符串.因为子字符串引用字符串,所以只要子字符串还在,系统就必须保持整个字符串.因此,无论何时操作完子字符串,都要将其转换为字符串.

let myString = String(mySubstring)

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

Swift 4的另一个重大改进是字符串是集合(再次).这意味着,无论对集合做什么,都可以对字符串做什么(使用下标、迭代字符、过滤器等).

下面的示例演示如何在Swift中获取子字符串.

Getting substrings

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

弦的开头

您可以使用下标(注意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

Converting Substring to String

别忘了,当你准备好保存你的子字符串时,你应该把它转换成String,这样旧字符串的内存就可以被清除了.

let myString = String(mySubstring)

Using an Int index extension?

在阅读了空速和奥勒·贝格曼(Ole Begemann)的文章Strings in Swift 3之后,我很犹豫是否使用基于Int的索引扩展.虽然在Swift 4中,字符串是集合,但Swift团队故意没有使用Int个索引.现在仍然是String.Index.这与由不同数量的Unicode代码点组成的快速字符有关.必须 for each 字符串唯一地计算实际索引.

我不得不说,我希望Swift团队能找到一种方法,在future 抽走String.Index名球员.但在它们出现之前,我 Select 使用它们的API.它帮助我记住字符串操作不仅仅是简单的Int索引查找.

Swift相关问答推荐

TabView中的视频播放器意外播放

@ MainActor + Combine不一致的编译器错误

为什么第二项任务不在第一项任务完成之前开始?(并发队列)

如何在SWIFT中轻松格式化公制和英制使用的UnitVolume

SwiftUI正在初始化不带状态变量的绑定变量

并发访问SWIFT中数组的非重叠子范围

如何让ScrollView缩小到合适的大小,并在没有黑客攻击的情况下占用最小空间

出错-无法将季节类型的值转换为预期的参数类型';[水果]';

为什么我的Swift app不能用xcodebuild构建,但是用XCode可以构建?

可以使 Swift init 仅可用于 Objective C 吗?

在这个使用 URLSession 的简单 case 中是否创建了一个强引用循环?

如何在 Swift 中使用子定义覆盖父类扩展

从 Swift 列表中的行中检索值

Swift 2 或 3 中的 Google Analytics 问题

如果没有标记,则为 Swift 预处理器

否定 #available 语句

为 UIImagePicker 设置委托返回错误

两个 Date 对象之间的所有日期 (Swift)

迭代 Firebase 中的子快照

转换为 swift 3 后,视图控制器中出现奇怪的通用函数