# 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 Int
s, 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
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
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)