Swift String.Index vs 将字符串转换为数组



在swift文档中,他们说他们使用String.Index来索引字符串,因为不同的字符可以占用不同的内存量。

但是我看到很多人将字符串转换为数组var a = Array(s)这样他们就可以按 int 而不是 String.Index 进行索引(这肯定更容易)

所以我想自己测试一下它是否对所有 unicode 字符完全相同:

let cafeA = "cafu{E9}" // eAcute
let cafeB = "cafu{65}u{301}" // combinedEAcute
let arrayCafeA = Array(cafeA)
let arrayCafeB = Array(cafeB)
print("(cafeA) is (cafeA.count) character (arrayCafeA.count)")
print("(cafeB) is (cafeB.count) character (arrayCafeB.count)")
print(cafeA == cafeB)
print("- A scalar")
for scalar in cafeA.unicodeScalars {
print(scalar.value)
}
print("- B scalar")
for scalar in cafeB.unicodeScalars {
print(scalar.value)
}

这是输出:

café is 4 character 4
café is 4 character 4
true
- A scalar
99
97
102
233
- B scalar
99
97
102
101
769

果然,正如文档中提到的,字符串只是一个字符数组,然后字素簇在字符对象中向下,那么他们为什么不通过 int 来索引它呢? 创建/使用String.Index实际上有什么意义?

在 String 中,字节表示形式是打包的,因此如果不从一开始就遍历整个字符串,就无法知道字符边界的位置。

当转换为数组时,这是遍历完成一次,结果是一个在内存中等距间隔的字符数组,这就是允许通过Int索引进行常量时间下标的原因。重要的是,数组被保留,因此可以对同一个数组执行许多下标操作,只需要遍历一次字符串的字节,即可进行初始解包。

可以使用下标扩展 String,该下标按Int索引它,您会看到它经常出现在 SO 上,但这是不明智的。标准库程序员本可以添加它,但他们故意选择不这样做,因为它掩盖了每个索引操作都需要单独遍历字符串字节的事实,这是O(string.count)。突然之间,像这样无害的代码:

for i in string.indices {
print(string[i]) // Looks O(1), but is actually O(string.count)!
}

变成二次。

最新更新