# Loops

# For-in loop

The for-in loop allows you to iterate over any sequence.

# Iterating over a range

You can iterate over both half-open and closed ranges:

for i in 0..<3 {
    print(i)
}

for i in 0...2 {
    print(i)
}

// Both print:
// 0
// 1
// 2

# Iterating over an array or set

let names = ["James", "Emily", "Miles"]

for name in names {
   print(name)
}

// James
// Emily
// Miles

If you need the index for each element in the array, you can use the enumerate() (opens new window) method on SequenceType (opens new window).

for (index, name) in names.enumerate() {
   print("The index of \(name) is \(index).")
}

// The index of James is 0.
// The index of Emily is 1.
// The index of Miles is 2.

enumerate() returns a lazy sequence containing pairs of elements with consecutive Ints, starting from 0. Therefore with arrays, these numbers will correspond to the given index of each element – however this may not be the case with other kinds of collections.

In Swift 3, enumerate() has been renamed to enumerated() (opens new window):

for (index, name) in names.enumerated() {
   print("The index of \(name) is \(index).")
}

# Iterating over a dictionary

let ages = ["James": 29, "Emily": 24]

for (name, age) in ages {
    print(name, "is", age, "years old.")
}

// Emily is 24 years old.
// James is 29 years old.

# Iterating in reverse

You can use the reverse() (opens new window) method on SequenceType (opens new window) in order to iterate over any sequence in reverse:

for i in (0..<3).reverse() {
    print(i)
}

for i in (0...2).reverse() {
    print(i)
}

// Both print:
// 2
// 1
// 0

let names = ["James", "Emily", "Miles"]

for name in names.reverse() {
    print(name)
}

// Miles
// Emily
// James

In Swift 3, reverse() has been renamed to reversed() (opens new window):

for i in (0..<3).reversed() {
    print(i)
}

# Iterating over ranges with custom stride

By using the stride(_:_:) (opens new window) methods on Strideable (opens new window) you can iterate over a range with a custom stride:

for i in 4.stride(to: 0, by: -2) {
    print(i)
}

// 4
// 2

for i in 4.stride(through: 0, by: -2) {
    print(i)
}

// 4
// 2
// 0

In Swift 3, the stride(_:_:) methods on Stridable have been replaced by the global stride(_:_:_:) (opens new window) functions:

for i in stride(from: 4, to: 0, by: -2) {
    print(i)
}

for i in stride(from: 4, through: 0, by: -2) {
    print(i)
}

# Repeat-while loop

Similar to the while loop, only the control statement is evaluated after the loop. Therefore, the loop will always execute at least once.

var i: Int = 0

repeat {
   print(i)
   i += 1
} while i < 3

// 0
// 1
// 2

# For-in loop with filtering

  1. where clause

By adding a where clause you can restrict the iterations to ones that satisfy the given condition.

for i in 0..<5 where i % 2 == 0 {
    print(i)
}

// 0
// 2
// 4


let names = ["James", "Emily", "Miles"]

for name in names where name.characters.contains("s") {
    print(name)
}

// James
// Miles

  1. case clause

It's useful when you need to iterate only through the values that match some pattern:

let points = [(5, 0), (31, 0), (5, 31)]
for case (_, 0) in points {
    print("point on x-axis")
}

//point on x-axis
//point on x-axis

Also you can filter optional values and unwrap them if appropriate by adding ? mark after binding constant:

let optionalNumbers = [31, 5, nil]
for case let number? in optionalNumbers {
    print(number)
}

//31    
//5

# Sequence Type forEach block

A type that conforms to the SequenceType protocol can iterate through it's elements within a closure:

collection.forEach { print($0) }

The same could also be done with a named parameter:

collection.forEach { item in
    print(item)
}

*Note: Control flow statements (such as break or continue) may not be used in these blocks. A return can be called, and if called, will immediately return the block for the current iteration (much like a continue would). The next iteration will then execute.

let arr = [1,2,3,4]

arr.forEach {
    
    // blocks for 3 and 4 will still be called
    if $0 == 2 {
        return
    }
}

# while loop

A while loop will execute as long as the condition is true.

var count = 1

while count < 10 {
    print("This is the \(count) run of the loop")
    count += 1
}

# Breaking a loop

A loop will execute as long as its condition remains true, but you can stop it manually using the break keyword. For example:

var peopleArray = ["John", "Nicole", "Thomas", "Richard", "Brian", "Novak", "Vick", "Amanda", "Sonya"]
var positionOfNovak = 0

for person in peopleArray {
    if person == "Novak" { break }
    positionOfNovak += 1
}

print("Novak is the element located on position [\(positionOfNovak)] in peopleArray.")
//prints out: Novak is the element located on position 5 in peopleArray. (which is true)

# Syntax

  • for constant in sequence { statements }
  • for constant in sequence where condition { statements }
  • for var variable in sequence { statements }
  • for _ in sequence { statements }
  • for case let constant in sequence { statements }
  • for case let constant in sequence where condition { statements }
  • for case var variable in sequence { statements }
  • while condition { statements }
  • repeat { statements } while condition
  • sequence.forEach(body: (Element) throws -> Void)