Does a for loop condition every loop in Swift?

I have a little discussion at work: is it good practice to quickly compute the size of an array before running elements over it? What would be better code practice:

Option A:

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

      

or option B:

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

      

That's all, of course, unless I change the Array during loops.

I have looked through the documentation which says:

The loop runs like this:

When the loop is first entered, the initialization expression is evaluated once to set any constants or variables that are required for the loop. The condition expression is evaluated. If false, the loop ends and code execution continues after the closing curly brace (}). If the expression evaluates to true, code execution continues by executing the statements within the curly braces. After all statements are executed, the increment expression is evaluated. This can increase or decrease the counter, or set one of the initialized variables to a new value based on the results of the statements. After the increment expression has been evaluated, execution returns to step 2 and the condition expression is evaluated again.

+3


source to share


3 answers


The idiomatic way to say it in Swift is:

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

      

Thus, evaluate and count nothing.

In fact, this would create a nice Array method:

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

      



Now you can just say:

mKeyboardTypesArray.setAllTo(false)

      

Alternatively, you can do it this way (it involves accepting count

, but only once):

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

      

+1


source


The loop condition is checked every time through the loop. Consider this experiment:

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])
}

      

Output:



here
1
here
2
here
3
here
4
here
5
here

You can see a slight speed improvement from Option B , but I would expect the property count

to be Array

not expensive if the array hasn't changed. This is potentially good code practice, as it tells the reader that you expect the size of the array to remain constant for the duration of the loop.

It is possible that the compiler will optimize array.count

by finding that nothing in the loop changes the array, but it will fail to do so for array.myCount

due to a side effect println

.

0


source


I found that this is not the case, which can cause a crash if you iterate over the array and remove elements (for example). In the current Swift syntax, this is for a loop

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

      

crashed in the middle of a bad index array.

I switched this to a while loop:

    var i: Int = 0
    while i < m_pendingCommands.count
    {
        if m_pendingCommands[i].packetID < ID
        {
            m_pendingCommands(at: i)
        }
        else
        {
            i += 1
        }
    }

      

0


source







All Articles