我认为这是一个必须要求所有语言的问题,但是当你写作时:
while i < array.count {
...
}
每次循环运行时,是否array.count
得到评估?在运行这样的循环之前,将它存储在let
常量中是否更好?
let length = array.count
while i < length {
...
}
答案 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
属性,因为它符合Collection
。 count
州Collection
的文档
复杂性:如果集合符合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