为啥 Swift 数组插入和 removeAtIndex 操作行为不一致?
Posted
技术标签:
【中文标题】为啥 Swift 数组插入和 removeAtIndex 操作行为不一致?【英文标题】:Why do Swift array insert and removeAtIndex operations behave inconsistently?为什么 Swift 数组插入和 removeAtIndex 操作行为不一致? 【发布时间】:2014-08-02 15:35:02 【问题描述】:我认为交换 Swift 数组的第 0 项和第 1 项是合法的,如下所示:
在索引 0 处调用 removeAtIndex,这会将第 1 项随机播放回索引 0 在索引 1 处插入已删除的项目。但我看到的行为不一致,具体取决于我的编码方式。
代码
func test()
class Test
var array = ["foo", "bar"]
func swap1() // PRODUCES STRANGE RESULT
array.insert(array.removeAtIndex(0), atIndex:1)
print("---swap1---", xs:array)
func swap2() // PRODUCES EXPECTED RESULT
let item = array.removeAtIndex(0)
array.insert(item, atIndex:1)
print("---swap2---", xs:array)
func swap3() // PRODUCES EXPECTED RESULT
var array = ["foo", "bar"]
array.insert(array.removeAtIndex(0), atIndex:1)
print("---swap3---", xs:array)
func print(fn: String, xs: [String])
println(fn)
for x in xs println(x)
Test().swap1()
Test().swap2()
Test().swap3()
输出
---swap1---
foo
foo
bar
---swap2---
bar
foo
---swap3---
bar
foo
出乎意料(对我来说),swap1() 克隆了第 0 个元素而不是删除它,从上面的 swap1 输出中重复的“foo”可以看出。似乎产生这种行为的特征是
将 removeAtIndex() 的结果作为第一个参数传递给 insert() 调用,而不是将其存储在中间常量中(后者由 swap2() 完成) 对类成员变量而不是函数局部变量进行操作(后者由 swap3() 完成)。我的问题:为什么 swap1() 行为不同?
【问题讨论】:
【参考方案1】:在同一个语句中有两个 array
的突变体。这通常是一个坏主意,并导致未定义的行为。这和你不想做的原因是一样的:
a = a++ + a++;
从人类的角度来看,很明显,您首先要删除一个项目,然后将其添加回已删除的数组中。
从编译器的角度来看,它必须做 3 件事来修改数组:1)读取原始数组的内容,2)修改内容,3)将它们写回。编译器必须在语句中这样做两次:
array.insert(array.removeAtIndex(0), atIndex:1)
您希望编译器这样做:
1) temp1 = array
2) temp1.removeItem
3) array = temp1
4) temp2 = array
5) temp2.addItem
6) array = temp2
但它确实做到了:
1) temp1 = array
2) temp2 = array
3) temp2.removeItem
4) array = temp2
5) temp1.addItem
6) array = temp1
编译器的操作顺序是允许的,这就是为什么你不应该在同一个语句中放置两个 mutator。
【讨论】:
我不确定这到底是怎么回事。由于其中一个 mutator 是另一个的参数,因此它们运行的顺序应该是明确定义的。 明确定义删除发生在插入之前,但没有明确定义插入是在删除之前还是之后存在的数组上操作。将数组视为要插入的第一个(隐藏)参数。在删除发生之前,可以读取该数组并将其放入堆栈(为插入调用做准备)。【参考方案2】:这似乎是 Swift 处理数组的一个副作用。我相信 Apple 仍在尝试找出在 Swift 中处理可变/不可变数组的最佳方法,并且这种行为可能会改变(并且在 beta 版中已经改变。
这是一篇很好的文章(或详细介绍到目前为止的一些行为和变化的文章流):
http://blog.human-friendly.com/swift-arrays-the-bugs-the-bad-and-the-ugly-incomplete
【讨论】:
以上是关于为啥 Swift 数组插入和 removeAtIndex 操作行为不一致?的主要内容,如果未能解决你的问题,请参考以下文章
Swift - 为啥 Process.arguments 返回空数组
为啥我不能在 Swift 中将对象数组返回给 UIStackView? [复制]
为啥我可以在 Swift 中更改 const 数组的成员? [复制]