在Swift中对数组调用reversed()
时,会得到一个ReverseCollection,它只是用reversed Access包装原始数组。因此,这是非常有效的:
let arr = [1,2,3,4]
for i in arr.reversed() { print(i) }
除了访问之外,没有什么东西实际上被逆转了;这里reversed
的时间复杂度为O(1)。酷!
但是,当我按整数索引到reversed()
并检查Quick Help时,我似乎失去了所有的效率;向我展示了序列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索引反转的效率?
是的,通过int
进行索引会导致您失去对反向数组的O(1)
访问。很抓到你了!
正如您所注意到的,reversed()
是一个重载的方法;在数组
上,有两个定义可供选择:
BidirectionalCollection.reversed()
,它返回reversedCollection
和sequence.reversed()
,它将任何序列转换为反向的[Element]
这里的重载对于数组
本身来说是最令人困惑的,因为它是序列
类型中唯一的类型(of:x)==type(of:x.reversist())
。
Swift类型检查器更喜欢更特定的重载,而不是更不特定的重载,因此一般情况下,编译器将尽可能使用BidirectionalCollection
重载,而不是Sequence
重载。rub:BidirectionalCollection
具有不透明的索引类型,不能使用int
进行索引;当使用int
索引到集合时,编译器将被迫选择sequence
重载而不是bidirectionalcollection
重载。这也是第二个代码示例编译失败的原因:Swift代码推断不考虑其他行的周围上下文;就其本身而言,rev
首选为reversedCollection
,因此试图用int
索引到它将失败。
您可以通过以下内容更清楚地看到这一点:
func seqType1<T: Collection>(_ s: T) {
print(T.self) // ReversedCollection<Array<Int>>
print(T.Index.self) // Index
}
func seqType2<T: Collection>(_ s: T) where T.Index == Int {
print(T.self) // Array<Int>
print(T.Index.self) // Int
}
let x: [Int] = [1, 2, 3]
seqType1(x.reversed())
seqType2(x.reversed())
当基于int
的索引似乎没有任何其他副作用时,为了避免您怀疑编译器是否可以围绕这一点进行优化,在编写本文时,答案似乎是“否”。Godbolt的输出有点太长,不能在这里复制,但目前,比较
func foo1(_ array: [Int]) {
if array.reversed()[100] > 42 {
print("Wow!")
}
}
与
func foo2(_ array: [Int]) {
if array.reversed().dropFirst(100).first! > 42 {
print("Wow!")
}
}
启用优化后显示foo2
执行直接数组访问
cmp qword ptr [rdi + 8*rax + 24], 43
问题内容: 这是Swift中的有效代码: 同样,输出将为真 将为假(数字1是任意的,您可以对-1进行相同的操作,可能还可以进行其他操作)。我问的原因是因为我看到一些试图将其与数字值进行比较的代码并将其编译,考虑return 似乎是错误的。 我的问题是,在Swift中这应该是有效的语法吗? 如果是这样,nil的数值是多少? Swift 3.0更新: 看起来Swift Evolution通过删除可选的
问题 你想要反转数组元素。 解决方案 使用 JavaScript Array 的 reverse() 方法: ["one", "two", "three"].reverse() # => ["three", "two", "one"] 讨论 reverse() 是标准的 JavaScript 方法,别忘了带圆括号。
问题内容: 在SQL I中,(不幸的)我经常不得不使用“ ”条件,因为数据库违反了几乎所有的规范化规则。我现在无法更改。但这与问题无关。 此外,我经常使用条件来提高SQL语句的可读性和灵活性。 有没有可能在不编写复杂的子选择的情况下将这两件事结合起来的方法? 我想要一些简单而不是这样的东西: 我在这里使用SQl Server和Oracle,但是我很感兴趣是否可以在任何RDBMS中实现。 问题答案:
我有一个链表数组,我正试图递归地反转它。当我调用函数反转时,它不会反转所有节点,而是反转几个节点。 反向功能似乎是删除第一个节点(基本情况)并用最后一个节点(子情况的结尾)填充其位置。我认为问题在于在reverse_nodes函数中调用for循环,但这似乎无法解决问题。 下面是一些输出。。 我试着让它倒过来,它写着:8,6,4,2 请注意,我只包含了相关的代码块,如结构体系结构、头/尾结构、在读取
问题内容: 在Swift中,是否有任何方法可以检查数组中是否存在索引而不会引发致命错误? 我希望我可以做这样的事情: 但是我明白了 致命错误:数组索引超出范围 问题答案: Swift中的一种优雅方式:
问题内容: 信不信由你,在分析当前代码后,numpy数组还原的重复操作将占用大量的运行时间。我现在拥有的是基于视图的常见方法: 还有其他方法可以更有效地执行此操作,还是我对不切实际的numpy性能的痴迷所致的幻觉? 问题答案: 创建时,您正在创建原始数组的视图。然后,您可以更改原始数组,并且视图将更新以反映所做的更改。 您是否经常需要重新创建视图?您应该能够执行以下操作: 我不是numpy专家,但