Swift array.count每次都在循环中得到评估

时间:2016-11-18 16:20:41

标签: swift

我认为这是一个必须要求所有语言的问题,但是当你写作时:

while i < array.count {
    ...
}
每次循环运行时,

是否array.count得到评估?在运行这样的循环之前,将它存储在let常量中是否更好?

let length = array.count
while i < length {
    ...
}

5 个答案:

答案 0 :(得分:6)

while循环(和do while循环)在每次迭代时都会对其谓词进行求值。

for循环评估序列一次。

以下是演示:

var array: [Int]

print("Test Case 1 - while i < array.count")
array = [1, 2, 3, 4, 5, 6]
var i = 0
while i < array.count {
    print(array[i])
    if i < 3 { array.append(123) }
    i += 1
}
print("\r\nTest Case 2 - for i in array.indices")
array = [1, 2, 3, 4, 5, 6]
for i in array.indices {
    print(array[i])
    if i < 3 { array.append(123) }
}

print("\r\nTest Case 3 - for i in 0 ..< array.count")
array = [1, 2, 3, 4, 5, 6]
for i in 0 ..< array.count {
    print(array[i])
    if i < 3 { array.append(123) }
}
  

测试案例1 - 而i&lt; array.count

     

1

     

2

     

3

     

4

     

5

     

6

     

123

     

123

     

123

     

测试用例2 - 对于array in array中的i

     

1

     

2

     

3

     

4

     

5

     

6

     

测试案例3 - 对于i在0 ..&lt; array.count

     

1

     

2

     

3

     

4

     

5

     

6

答案 1 :(得分:3)

是的,它会在每次迭代时进行评估。

分配一个常量会稍微提高一点。然而,在现代编译器中进行所有优化后,我不会感到烦恼。除非循环计数很大。

答案 2 :(得分:3)

Array获取count属性,因为它符合CollectioncountCollection的文档

  

复杂性:如果集合符合RandomAccessCollection,则为O(1);否则,O(n),其中n是集合的长度。    - Source

由于Array也符合RandomAccessCollection,因此获取数组计数是一个恒定时间操作。在开始时获得一次与每次循环迭代之间不应该有任何重大的性能差异。

答案 3 :(得分:1)

小心如下所示的for循环。由于elems.count是在循环顶部构造一次的范围的一部分,因此它只被评估一次。 i = 4

时,以下代码将会死亡
var elems = [1, 2, 3, 4, 5, 6]

for i in 0 ..< elems.count {
    if i % 2 == 0 { // remove even elements
        elems.remove(at: i)
    }
}

每次评估条件时,array.count中的while确实会得到评估。

答案 4 :(得分:0)

是的,每次都会调用

让我们运行一个简单的测试,首先我们需要以下数组扩展

extension Array {
    var myCustomCount: Int {
        print("myCustomCount")
        return self.count
    }
}

然后我们可以试试这段代码

let nums = [1, 2, 3, 4, 5]
var i = 0
while i < nums.myCustomCount {
    i += 1
}

输出

myCustomCount
myCustomCount
myCustomCount
myCustomCount
myCustomCount
myCustomCount

enter image description here