Swift数组.count是否在循环中每次都被求值

5n0oy7gb  于 2023-03-07  发布在  Swift
关注(0)|答案(5)|浏览(132)

我想这是一个每种语言都必须问的问题,但当你写例如:

while i < array.count {
    ...
}

array.count是否在每次循环运行时都被求值?在像这样运行循环之前将其存储在一个let常量中是否更好?

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

gg0vcinb1#

是的,每次为循环计算条件时都会访问该值。在问题的示例中,由于Array的实现方式不同,因此将其移到变量中没有区别。
Array获得count属性,因为它符合CollectionCollectioncount的文档说明
复杂度:O(1),如果集合符合随机访问集合;否则为O(n),其中n是集合的长度。

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

t40tm48m

t40tm48m2#

while循环(和do while循环)在每次迭代时都会计算其 predicate 。
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) }
}
  • Test Case 1 - while i < array.count
1
2
3
4
5
6
123
123
123
  • Test Case 2 - for i in array.indices
1
  2
  3
  4
  5
  6
  • Test Case 3 - for i in 0 ..< array.count
1
2
3
4
5
6
yws3nbqq

yws3nbqq3#

是的,它在每次迭代中进行评估。
赋值给常量会稍微好一点,但是对于现代编译器的所有优化,我不会去麻烦,除非循环计数是巨大的。

8zzbczxx

8zzbczxx4#

小心下面的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)
    }
}

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

4ngedf3f

4ngedf3f5#

是的,每次都会调用它

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

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

相关问题