For loop, for each, while, and repeat. Iterating in Swift

For loop, for each, and repeat are examples of control flow statements in Swift. Although most of them look similar, there are differences. Let’s go over them.

For loop and collections

The for loop might be the most well-known method for iteration over all programming languages. It’s also known as the for-in loop in Swift.

For-In loop with collections

This example iterates over an array of cities, also known as a collection in Swift.

let cities = ["Amsterdam", "New York", "San Francisco"]
for city in cities {
    print(city)
}

// Amsterdam
// New York
// San Francisco

For-In loop with dictionaries

This example iterates over a dictionary. In here, it prints out the age of each person.

let ages = ["Antoine": 28, "Jaap": 2, "Jack": 72]
for (name, age) in ages {
    print("\(name) is \(age) years old")
}

// Antoine is 28 years old
// Jaap is 2 years old
// Jack is 72 years old

Combining a for loop with ranges

The following example uses a range to execute the print statement 4 times. Fun fact, we’re reversing the order so we create a countdown. This is done easily inline and can also be used in other loops. Another example is sorting the collection like this.

for index in (0...3).reversed() {
    print("\(index)..")
}

/// 3..
/// 2..
/// 1..
/// 0..

Iterating over an array using forEach

The above examples can be used in a for each loop as well. In fact, forEach calls the given closure on each element in the sequence in the same order as a for-in loop.

let cities = ["Amsterdam", "New York", "San Francisco"]
cities.forEach { city in
    print(city)
}

// Amsterdam
// New York
// San Francisco

let ages = ["Antoine": 28, "Jaap": 2, "Jack": 72]
ages.forEach { name, age in
    print("\(name) is \(age) years old")
}

// Antoine is 28 years old
// Jaap is 2 years old
// Jack is 72 years old

(0...3).reversed().forEach { index in
    print("\(index)..")
}

// 3..
// 2..
// 1..
// 0..

ForIn vs forEach

Although the examples above seem to show the same behaviors, this is not completely true. Using the forEach method is distinct from a for-in loop in two important ways:

  1. The break or continue statement cannot be used to exit the current call of the body closure or to skip subsequent calls.
  2. Using the return statement in the body closure will only exit the closure and not the outer scope, and it won’t skip subsequent calls.

An example of the differences

The following example collects the first 10 even numbers of a collection of numbers. For this, we’re using the break and continue statements. The break statement stops the loop, while the continue statements are used to skip the current number.

var evenNumbers = [Int]()
for number in (0...100) {
    guard evenNumbers.count < 10 else {
        break
    }

    guard number % 2 == 0 else {
        continue
    }
    evenNumbers.append(number)
}
print(evenNumbers)

// [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]

We can’t use the break and continue statements using forEach. Therefore, we’re using a filter to get all the even numbers combined with a prefix to get the first 10 items.

let evenNumbers = (0...100).filter { number -> Bool in
    return number % 2 == 0
}.prefix(10)

print(evenNumbers)

// [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]

While loops

While loops are less often used, but can be really useful. It’s basically executing its statements while the condition is true. The following example is rolling dice until the max amount of tries is reached.

func rollDice() -> Int {
    return (1...6).randomElement()!
}

let maxTries = 6
var tries = 0
var score = 0

while tries < maxTries {
    score += rollDice()
    tries += 1
}

print("Total score is \(score)") // Everytime a random new score! 

Repeat while loops

The repeat while loops is also known as the do while in other languages. It executes a single pass through the block before evaluating the condition. We could write the above example as followed.

repeat {
    score += rollDice()
    tries += 1
} while tries < maxTries

print("Total score is \(score)")

While vs Repeat While

The main difference between the while and repeat while statements are the moment of evaluating the condition. The repeat while will always execute the block once before the condition is read. Best way to describe the difference is the following tweet by David Rousset.

 

Combining loops with where

A For in loop can be combined with the where keyword. To learn more about this, check out Where usage in Swift.