在迭代其范围时修改Swift数组 - 0到count,startIndex到endIndex

时间:2017-12-24 06:11:58

标签: arrays swift iteration

我是Swift的新手,我正在探索如果在使用Range迭代它时修改集合会发生什么。我无法弄清楚为什么这两个循环有不同的行为:

var things = ["a", "b", "c"]
for i in 0..<things.count {
    print("i: \(i) count: \(things.count) value: \(things[i])")
    if i == 1 {
        things.append("x")
    }
}
// i: 0 count: 3 value: a
// i: 1 count: 3 value: b
// i: 2 count: 4 value: c

VS

var things = ["a", "b", "c"]
for i in things.startIndex...things.endIndex {
    print("i: \(i) count: \(things.count) value: \(things[i])")
    if i == 1 {
        things.append("x")
    }
}
// i: 0 count: 3 value: a
// i: 1 count: 3 value: b
// i: 2 count: 4 value: c
// i: 3 count: 4 value: x

我创建了这个Array类扩展,所以我可以看到Range文字何时访问数组的属性:

extension Array {
    var myCount: Int {
        print("myCount (\(self.count))")
        return self.count
    }
    var myStartIndex: Int {
        print("myStartIndex (\(self.startIndex))")
        return self.startIndex
    }
    var myEndIndex: Int {
        print("myEndIndex (\(self.endIndex))")
        return self.endIndex
    }
}

如果我使用这些属性而不是正常属性,我会得到:

myCount (3)
i: 0 count: 3 value: a
i: 1 count: 3 value: b
i: 2 count: 4 value: c

myStartIndex (0)
myEndIndex (3)
i: 0 count: 3 value: a
i: 1 count: 3 value: b
i: 2 count: 4 value: c
i: 3 count: 4 value: x

我一定错过了什么,因为这感觉就像魔术!似乎endIndex正在重新评估,但count不是。是什么给了什么?

1 个答案:

答案 0 :(得分:2)

这是因为在第一段代码中,您使用了半开放范围运算符..<),而在第二段代码中使用了正常范围运算符( ...)。 他们是不同的。来自apple docs

  

半开范围运算符(a..<b)定义了从a到b的范围,但不包括b。

因此,如果for为4,则第一段代码中的things.count循环不会继续,因为当与半开放范围运算符一起使用时,范围(0 - 4)仅在{ {1}}为0,1,2或3。

如果您使用i代替...,则第一段代码的结果将与第二段相同。