【问题标题】:Does for ... in loop loop through a copy of a sequence?for ... in 循环是否遍历序列的副本?
【发布时间】:2020-07-06 08:24:11
【问题描述】:

我在 Matt Neuburg 的 iOS 13 Programming Fundamentals with Swift 中遇到过如下陈述:

当您使用 for...in 循环浏览一个序列时,您实际上循环浏览的是该序列的副本。这意味着在循环过程中改变序列是安全的:

作者为上述陈述提供了以下示例:

var s : Set = [1,2,3,4,5]
for i in s {
    if i.isMultiple(of:2) {
        s.remove(i)
    }
} // s is now [1,3,5]

在上面的示例中,我们可以看到原始数组从 [1,2,3,4,5,6] 更改为 [1,3,5]。这意味着数组本身已更改。所以,for in 循环不是循环通过原始数组的副本,而是数组本身。这似乎与作者上面的陈述相矛盾。

所以,我不确定作者的陈述是否属实。有人请澄清这个问题吗?非常感谢。

【问题讨论】:

标签: arrays swift loops for-in-loop


【解决方案1】:

乍一看,措辞可能有点误导,但for i in s 循环遍历原始s 的副本的说法是正确的。如果它不是真的,你会得到一个超出范围的异常或一个意外的结果(集合的某些元素被跳过),因为你会在迭代时改变一个集合。

当您使用for i in s 创建循环时,会创建s 的副本,并通过该副本进行迭代。但是,当您在循环体内访问 s 时,您访问的是原始 s 并因此对其进行变异,而不是变异循环正在迭代的副本。

【讨论】:

    【解决方案2】:

    这里有一点细微差别。您迭代的数组是一个副本,但您正在修改的数组仍然是原始数组。

    在其他情况下,由于索引更改,此代码最终会跳过一些元素。

    如果不是这样,请考虑以下迭代

    // i = 0
    // s = [1,2,3,4,5]
    // evaluation 1.isMultiple(of: 2)
    // element to be removed: none
    
    // i = 1
    // s = [1,2,3,4,5]
    // evaluation 2.isMultiple(of: 2)
    // element to be removed: 2
    
    // Here is where the problems would start, since the number 3 would be skipped.
    // i = 2
    // s = [1,3,4,5]
    // evaluation 4.isMultiple(of: 2)
    // element to be removed: 2
    

    由于您正在迭代副本,因此您可以修改 s 并仍然确保将考虑所有元素。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-03-04
      • 2011-02-02
      • 2019-04-13
      • 2020-11-17
      • 1970-01-01
      • 2016-04-14
      相关资源
      最近更新 更多