为什么 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"