var str = "Hello"
print(str.characters) // CharacterView(_core: Swift._StringCore(_baseAddress: Optional(0x000000011c9a68a0), _countAndFlags: 5, _owner: nil))
print(str.characters.index(of: "o")!) // Index(_base: Swift.String.UnicodeScalarView.Index(_position: 4), _countUTF16: 1)
print(Array(str.characters)) // ["H", "e", "l", "l", "o"]
print(str.characters.map{String($0)}) //["H", "e", "l", "l", "o"]
for character in str.characters{
print(character)
}
// H
// e
// l
// l
// o
我看了this个问题。我从Swift参考中查看String
并找到:var characters: String.CharacterView
。
但是我想知道究竟是str.characters
返回了什么?我怎么能枚举这么容易,或转换它到一个数组或映射它然后打印它自己甚至当索引到它打印如此乱码
我很确定我不理解的是因为不理解characterView
。我希望是否有人可以在这个问题上给一个非专业人员概述它的作用和含义。
答案 0 :(得分:2)
str.characters
会返回String.CharacterView
- 在字符串的字符上显示视图,允许您访问它们而无需将内容复制到新的缓冲区(而Array(str.characters)
或str.characters.map{...}
只会这样做。)
String.CharacterView
本身是一个Collection
,它由一个String.CharacterView.Index
(一个不透明的索引类型)索引,并且具有Character
类型的元素(不出所料)(代表一个扩展名)字形集群 - 通常读者会认为是“单个字符”。
let str = "Hello"
// indexed by a String.Index (aka String.CharacterView.Index)
let indexOfO = str.characters.index(of: "o")!
// element of type Character
let o = str.characters[indexOfO]
// String.CharacterView.IndexDistance (the type used to offset an index) is of type Int
let thirdLetterIndex = str.characters.index(str.startIndex, offsetBy: 2)
// Note that although String itself isn't a Collection, it implements some convenience
// methods, such as index(after:) that simply forward to the CharacterView
let secondLetter = str[str.index(after: str.startIndex)]
由特殊String.CharacterView.Index
而不是例如Int
索引的原因是字符可以使用不同的字节长度进行编码。因此,下标可能是(在非ASCII存储字符串的情况下)O(n)操作(需要迭代编码的字符串)。但是,使用Int
下标自然感觉它应该是O(1)操作(便宜,不需要迭代)。
str.characters[str.characters.index(str.characters.startIndex, offsetBy: n)] // feels O(n)
str.characters[n] // illegal, feels O(1)
我如何能够如此轻易地枚举它,或将其转换为数组或映射它,然后将其自身打印,或者甚至在索引到它时打印如此乱码
您可以枚举,转换为Array
和map(_:)
String.CharacterView
只是因为它是Collection
- 因此符合Sequence
,这允许for ... in
循环以及使用map(_:)
和Array(_:)
构造函数等。
至于为什么打印str.characters
导致“乱码”的原因在于它根本不通过符合CustomStringConvertible
或CustomDebugStringConvertible
来提供自己的自定义文本表示