我讨厌 Swift String
不允许你使用 Int
来访问它们的字符。这个包改变了这一点。
someString[someString.index(someString.startIndex, offsetBy: 2) ... someString.index(someString.startIndex, offsetBy: 5)]
变为这样:
import StringIntegerAccess
var someString = "Hello, World!"
someString[1...4] // "ello"
someString[7..<12] = "Mars" // "Hello, Mars!"
如果您愿意,您还可以放心,无论您传递什么整数,它都不会崩溃!从 2.0.0
版本开始,您现在可以使用 [orNil:]
下标,它将返回与常规下标相同的值,但是如果您给它们超出范围的索引,它们将返回 nil
而不是崩溃。
import SafeStringIntegerAccess
var someString = "Hello, World"
someString[orNil: 3..<5] == "lo"
someString[orNil: 3..<5] == someString[3..<5]
someString[orNil: 42..<99] == nil
someString[orNil: -10 ..< -5] == nil
someString[orNil: 7...] = "Mars!" // "Hello, Mars!"
someString[orNil: 999...] = "Boundaries" // "Hello, Mars!"
更棒的是,这也隐式导入了 StringIntegerAccess
,因此您不必重复导入!
这与它缩短的长形式**性能完全相同**。也就是说,长形式通常性能不是很高。正如 Rob Napier 在 StackOverflow 上指出的,由于 Swift String
元素是 Unicode 字符,并且 Unicode 字符是长度不确定的码位,并且 String
的存储由 UTF-8 码位组成,因此没有简单的方法知道一个字符有多大,所以你不能直接跳到字符串中的任何位置,而必须先读取它之前的所有内容。为了找出“字符 n”,您必须从头开始并解码所有内容,这是 O(n)。
所以你写出这样的代码,感觉非常“安全”
for index in 0..<string.count { print(string[index]) }但实际上这是 O(n^2),这真的很令人惊讶,因为它看起来像是 O(n)。你可能会说“好吧,我的字符串只有 20 个字符长,所以谁在乎”,但我们使用字符串做很多事情,包括多兆字节的
NSTextStorage
。(而且这在 Swift 中比其他一些语言扩展得更快,因为 Swift 包括通用算法,其性能承诺依赖于下标操作是 O(1) 这一事实。)
您还可以了解更多关于为什么这样做的信息,在我关于为什么像 👩👩👧👦
这样的表情符号在 Swift String
中受到如此奇怪的对待的 StackOverflow 问题中。
"\u{1112}\u{1161}\u{11AB}".contains("\u{1112}") // false
如果您正在解析大型字符串,无论如何您都应该意识到这一点。这里值得指出的是,这种语法糖只是使酸涩后端的接口变得甜美。如果您正在读取和使用大量数据,则应使用 Data
类型,它已经有 Int
下标。