当你打电话的时候 reversed()
在swift中的数组上,您会得到一个reversecollection,它仅使用反向访问来 Package 原始数组。因此,这是非常有效的:
let arr = [1,2,3,4]
for i in arr.reversed() { print(i) }
除了进入通道,实际上没有任何东西被反转;时间复杂性 reversed
这是o(1)。酷!
但当我索引到 reversed()
通过一个整数并检查快速帮助,似乎我已经失去了所有的效率;我看到了序列 reversed()
这将生成一个新数组:
let arr = [1,2,3,4]
let i = arr.reversed()[1] // ???? this is a different `reversed()`!
这似乎是真的,因为 reversed()
数组本身不支持按数字索引:
let arr = [1,2,3,4]
let rev = arr.reversed()
let i = rev[1] // compile error!
所以我的问题是:按数字索引到 reversed()
在我的第二个示例中,数组失去了reversecollection索引Reversion的效率?
1条答案
按热度按时间cu6pst1q1#
是的,索引由
Int
是不是让你失去了理智O(1)
访问反向阵列。完全明白了!正如你所注意到的,
reversed()
这里是一个重载方法;在…上Array
具体而言,您有两个定义可供选择:BidirectionalCollection.reversed()
,返回一个ReversedCollection
,及Sequence.reversed()
,它将任何序列转换为反向序列[Element]
这里的重载最让人困惑Array
它本身,因为它是唯一的Sequence
打字使type(of: x) == type(of: x.reversed())
.swift类型检查器更喜欢更具体的重载,而不是不太具体的重载,因此一般来说,编译器将使用
BidirectionalCollection
重载而不是Sequence
在可能的情况下。难点在于:BidirectionalCollection
具有不透明索引类型,不能使用Int
; 当您使用Int
,编译器将被迫选择Sequence
超载BidirectionalCollection
一个。这也是您的第二个代码示例未能编译的原因:swift代码推理没有考虑其他行上的周围上下文;就其本身而言,rev
最好是一名教师ReversedCollection<Array<Int>>
,因此尝试使用Int
失败。您可以通过以下内容更清楚地看到这一点:
以免您怀疑编译器是否可以在
Int
-基于索引的索引似乎没有任何其他副作用,在撰写本文时,答案似乎是“否”。godbolt输出有点太长,无法在此处复制,但目前,比较具有
启用优化后,将显示
foo2
执行直接阵列访问优化了
ReversedCollection
完全 Package ,而foo1
经历了明显更多的间接过程。