为什么 Swift 标准库 return Reverse RandomAccessCollection 中的 reverse() 函数?
Why does the reverse() function in the Swift standard library return ReverseRandomAccessCollection?
既然我已经学会了Swift(达到了一个合理的水平),我正在努力掌握标准库,但实际上它对我来说主要是ελληνικά!
所以一个具体的问题:我有一个字符串数组,我可以对其调用 reverse()。
let arr = ["Mykonos", "Rhodes", "Naxos"].reverse()
现在我天真地以为我会从中得到一种数组。 (Ruby 例如有一个类似的方法,你传递一个数组并取回一个数组)
但是 arr 现在实际上是类型
ReverseRandomAccessCollection<Array<String>>
实际上是一个结构体,符合CollectionType:
public struct ReverseRandomAccessCollection<Base : CollectionType where Base.Index : RandomAccessIndexType> : _ReverseCollectionType
这意味着我可以做到:
for item in arr {
print(item)
}
但是我做不到
print(arr[0])
为什么要这样设计?
Swift 中的字典也实现了 CollectionType,所以我可以这样做:
let dict = ["greek" : "swift sometimes", "notgreek" : "ruby for this example"].reverse()
但是字典不像数组那样有序,所以为什么我可以在字典上调用 reverse()?
如果有人能指出我可以阅读和改进我的 Swift stdlib foo 的方向,我将加分,Eυχαριστώ!
这是对时间和内存的性能优化。
ReverseRandomAccessCollection
表示的元素
原数组倒序,无需创建新数组
并复制所有元素(只要原始数组不是
变异了)。
您可以访问带下标的反转元素:
let el0 = arr[arr.startIndex]
let el2 = arr[arr.startIndex.advancedBy(2)]
或
for i in arr.indices {
print(arr[i])
}
您还可以使用
显式创建数组
let reversed = Array(["Mykonos", "Rhodes", "Naxos"].reversed())
一个字典也是一个Key/Value对的序列。在
let dict = ["greek" : "swift sometimes", "notgreek" : "ruby for this example"].reverse()
调用了一个完全不同的reversed()
方法:
extension SequenceType {
/// Return an `Array` containing the elements of `self` in reverse
/// order.
///
/// Complexity: O(N), where N is the length of `self`.
@warn_unused_result
public func reversed() -> [Self.Generator.Element]
}
结果是一个包含 Key/Value 对字典的数组
以相反的顺序。但这用途有限,因为订单
字典中的 Key/Value 对可以是任意的。
来自 language docs of ReverseCollention
(.reverse()
的结果):
The reverse() method is always lazy when applied to a collection with
bidirectional indices, but does not implicitly confer laziness on
algorithms applied to its result.
In other words, for ordinary collections c having bidirectional indices:
- c.reverse() does not create new storage
...
因此,您可以将 ReverseRandomAccessCollection
视为 尚未反转的 数组的随机访问包装器(即,您的原始数组 arr
尚未尚未被复制并反转到内存中的新位置)。
自然地,从上面可以看出,你不能直接索引反向集合,因为 Array
提供访问作为指向保存数组的内存的指针,索引对应于按位进行(取决于类型)在内存中转发。但是,我们仍然可以使用 ReverseRandomAccessIndex
:
以数组索引样式访问 "reverse array" 的元素
let arr = ["Mykonos", "Rhodes", "Naxos"]
let arrReverse = arr.reverse()
/* ReverseRandomAccessCollection access "wrapper" over
the 'arr' data in memory. No new storage allocated */
let myIndex = arrReverse.startIndex.advancedBy(2)
/* bIndex type:
ReverseRandomAccessIndex<ReverseRandomAccessIndex<Index>> */
print(arrReverse[myIndex]) // "Mykonos"
相反,我们可以显式地为我们的反向数组分配内存,并像对待任何其他数组一样对待它。在这一点上,arrReverse
是一个不同于 arr
的数组,并且与前者没有任何关系,除了(一次)是通过使用它创建的。
let arr = ["Mykonos", "Rhodes", "Naxos"]
let arrReverse = Array(arr.reverse())
/* Array<String> */
let myIndex = arrReverse.startIndex.advancedBy(2)
/* bIndex type: Int */
print(arrReverse[myIndex]) // "Mykonos"
Martin R 先于我,所以请参阅他关于 词典.
的注释
使用Swift3.0,可以直接通过索引访问Array值。
var streets = ["Albemarle", "Brandywine", "Chesapeake"]
streets = streets.reversed()
print("Array at index is \(streets[0])")
这将打印 "Chesapeake"
既然我已经学会了Swift(达到了一个合理的水平),我正在努力掌握标准库,但实际上它对我来说主要是ελληνικά!
所以一个具体的问题:我有一个字符串数组,我可以对其调用 reverse()。
let arr = ["Mykonos", "Rhodes", "Naxos"].reverse()
现在我天真地以为我会从中得到一种数组。 (Ruby 例如有一个类似的方法,你传递一个数组并取回一个数组)
但是 arr 现在实际上是类型
ReverseRandomAccessCollection<Array<String>>
实际上是一个结构体,符合CollectionType:
public struct ReverseRandomAccessCollection<Base : CollectionType where Base.Index : RandomAccessIndexType> : _ReverseCollectionType
这意味着我可以做到:
for item in arr {
print(item)
}
但是我做不到
print(arr[0])
为什么要这样设计?
Swift 中的字典也实现了 CollectionType,所以我可以这样做:
let dict = ["greek" : "swift sometimes", "notgreek" : "ruby for this example"].reverse()
但是字典不像数组那样有序,所以为什么我可以在字典上调用 reverse()?
如果有人能指出我可以阅读和改进我的 Swift stdlib foo 的方向,我将加分,Eυχαριστώ!
这是对时间和内存的性能优化。
ReverseRandomAccessCollection
表示的元素
原数组倒序,无需创建新数组
并复制所有元素(只要原始数组不是
变异了)。
您可以访问带下标的反转元素:
let el0 = arr[arr.startIndex]
let el2 = arr[arr.startIndex.advancedBy(2)]
或
for i in arr.indices {
print(arr[i])
}
您还可以使用
显式创建数组let reversed = Array(["Mykonos", "Rhodes", "Naxos"].reversed())
一个字典也是一个Key/Value对的序列。在
let dict = ["greek" : "swift sometimes", "notgreek" : "ruby for this example"].reverse()
调用了一个完全不同的reversed()
方法:
extension SequenceType {
/// Return an `Array` containing the elements of `self` in reverse
/// order.
///
/// Complexity: O(N), where N is the length of `self`.
@warn_unused_result
public func reversed() -> [Self.Generator.Element]
}
结果是一个包含 Key/Value 对字典的数组 以相反的顺序。但这用途有限,因为订单 字典中的 Key/Value 对可以是任意的。
来自 language docs of ReverseCollention
(.reverse()
的结果):
The reverse() method is always lazy when applied to a collection with bidirectional indices, but does not implicitly confer laziness on algorithms applied to its result.
In other words, for ordinary collections c having bidirectional indices:
- c.reverse() does not create new storage
...
因此,您可以将 ReverseRandomAccessCollection
视为 尚未反转的 数组的随机访问包装器(即,您的原始数组 arr
尚未尚未被复制并反转到内存中的新位置)。
自然地,从上面可以看出,你不能直接索引反向集合,因为 Array
提供访问作为指向保存数组的内存的指针,索引对应于按位进行(取决于类型)在内存中转发。但是,我们仍然可以使用 ReverseRandomAccessIndex
:
let arr = ["Mykonos", "Rhodes", "Naxos"]
let arrReverse = arr.reverse()
/* ReverseRandomAccessCollection access "wrapper" over
the 'arr' data in memory. No new storage allocated */
let myIndex = arrReverse.startIndex.advancedBy(2)
/* bIndex type:
ReverseRandomAccessIndex<ReverseRandomAccessIndex<Index>> */
print(arrReverse[myIndex]) // "Mykonos"
相反,我们可以显式地为我们的反向数组分配内存,并像对待任何其他数组一样对待它。在这一点上,arrReverse
是一个不同于 arr
的数组,并且与前者没有任何关系,除了(一次)是通过使用它创建的。
let arr = ["Mykonos", "Rhodes", "Naxos"]
let arrReverse = Array(arr.reverse())
/* Array<String> */
let myIndex = arrReverse.startIndex.advancedBy(2)
/* bIndex type: Int */
print(arrReverse[myIndex]) // "Mykonos"
Martin R 先于我,所以请参阅他关于 词典.
的注释使用Swift3.0,可以直接通过索引访问Array值。
var streets = ["Albemarle", "Brandywine", "Chesapeake"]
streets = streets.reversed()
print("Array at index is \(streets[0])")
这将打印 "Chesapeake"