for循环条件是否评估了Swift中的每个循环?

时间:2015-07-05 22:26:40

标签: swift for-loop

我在工作中有一个小小的争论:在运行它的项目之前,在swift中计算数组的大小是一个好习惯吗?什么是更好的代码实践:

选项A:

    func setAllToFalse() {
        for (var i = 0; i < mKeyboardTypesArray.count; i++ ) {
            self.mKeyboardTypesArray[i] = false
        }
    }

选项B:

    func setAllToFalse() {
        let typesCount = mKeyboardTypesArray.count
        for (var i = 0; i < typesCount; i++ ) {
            self.mKeyboardTypesArray[i] = false
        }
    }

当然,如果我在循环期间不改变数组,那么全部。

我确实查看了文档,其中说明了这一点:

  

循环执行如下:

     

首次进入循环时,初始化表达式为   评估一次,以设置所需的任何常量或变量   为循环。评估条件表达式。如果它评估   如果为false,则循环结束,代码在for之后继续执行   loop的右括号(})。如果表达式的计算结果为true,则为code   通过执行大括号内的语句继续执行。   执行完所有语句后,增量表达式为   评估。它可能会增加或减少计数器的价值,或   将其中一个初始化变量设置为基于的新值   声明的结果。增量表达式之后   评估,执行返回到步骤2,以及条件表达式   再次评估。

3 个答案:

答案 0 :(得分:1)

在Swift中说这个的惯用方法是:

func setAllToFalse() {
    mKeyboardTypesArray = mKeyboardTypesArray.map {_ in false}
}

这样,没有什么可以评估的,也没有什么可计算的。

实际上,这会产生一个很好的Array方法:

extension Array {
    mutating func setAllTo(newValue:T) {
        self = self.map {_ in newValue}
    }
}

现在你可以说:

mKeyboardTypesArray.setAllTo(false)

或者,你可以这样做(这涉及到count,但只有一次):

mKeyboardTypesArray = Array(count:mKeyboardTypesArray.count, repeatedValue:false)

答案 1 :(得分:0)

每次循环评估循环条件。考虑一下这个实验:

extension Array {
    var myCount: Int {
        get {
            println("here")
            return self.count
        }
    }
}

let a = [1, 2, 3, 4, 5]

for var i = 0; i < a.myCount; i++ {
    println(a[i])
}

输出:

  

这里
1在这里
2
这里
3这里这里是4 <这里是

你可以从选项B 看到一个小的速度提升,但我希望如果数组不变,count上的Array属性并不昂贵。无论如何,这可能是一个很好的代码实践,因为它会向读者传达您希望数组大小在循环持续时间内保持不变。

编译器可能会通过检测循环中的任何内容修改数组来优化array.count,但由于{array.myCount,它无法为println执行此操作。 1}}副作用。

答案 2 :(得分:0)

我发现事实并非如此,如果您遍历数组并删除项目(例如),可能会导致崩溃。在当前的Swift语法中,此for循环

WifiManager myWifiManager;
myWifiManager = (WifiManager) getSystemService(WIFI_SERVICE);
myWifiManager.startScan();
List<ScanResult> scanList = myWifiManager.getScanResults();
Collections.sort(scanList);

在数组中途丢失,索引错误。

我将其切换为while循环:

        for i in 0..<m_pendingCommands.count
        {
            if m_pendingCommands[i].packetID < command.packetID
            {
                m_pendingCommands.remove(at: i)
            }
        }