Start learning free

LESSON 276 OF 678 · TUPLES, SORTING & BUILT-INS

enumerated and zip in Swift: Looping with Counts and Pairs

Lesson Read the full explanation

TL ; DR:

enumerated() gives each item with a count. zip walks two arrays side by side.


let fruits = ["apple", "kiwi", "plum"]
let prices = [3, 1, 2]

for (i, fruit) in fruits.enumerated() {
    print("\(i + 1). \(fruit)")    // 1. apple, then 2. kiwi, then 3. plum
}

for (fruit, price) in zip(fruits, prices) {
    print("\(fruit) \(price)")     // apple 3, then kiwi 1, then plum 2
}


Full lesson:

You have looped with for i in 0..<meals.count. Then meals[i] gave the item. Swift has a shorter way to get both.

enumerated() gives each item together with a count. The loop unpacks the tuple into two names, as let (name, age) = pet does.

for (i, meal) in meals.enumerated() {
    print("\(i) \(meal)")
}

The count comes first. It starts at 0, so print i + 1 for a numbered list.

zip(a, b) walks two arrays side by side. It pairs the first item of a with the first item of b. Then it pairs the second items, and so on. Each pair is a tuple.

for (fruit, price) in zip(fruits, prices) {
    print("\(fruit) costs \(price)")
}

zip is a function, not a method of the array. Write zip(fruits, prices), not fruits.zip(prices).

zip stops at the end of the shorter array. The extra items are skipped, with no error.

The two work together. zip(fruits, prices).enumerated() gives a count and a pair each time. The names nest the same way.

for (i, (fruit, price)) in zip(fruits, prices).enumerated() {
    print("\(i + 1). \(fruit) costs \(price)")
}

Your task

A quiz show keeps its players in the array players. Their points are in scores, in the same order.

First, print the players as a numbered list from 1, like 1. Ana. Use enumerated().

Then print each player with their points, like Ana has 12 points. Use zip.

Expected output:

1. Ana
2. Ben
3. Cleo
Ana has 12 points
Ben has 9 points
Cleo has 15 points
STEP 1 OF 4
    Ctrl + Enter to check

    SWIFT · TUPLES, SORTING & BUILT-INS

    Enumerate And Zip in Swift, explained

    Getting the item and its count

    A loop such as for i in 0..<meals.count gives you an index, and then meals[i] gives the item. Swift has a shorter way to get both at once. enumerated() gives each item together with a count, as a tuple, and the loop unpacks that tuple into two names:

    let fruits = ["apple", "kiwi", "plum"]
    for (i, fruit) in fruits.enumerated() {
        print("\(i) \(fruit)")
    }
    
    0 apple
    1 kiwi
    2 plum
    

    The count comes first, then the item. It starts at 0, so print i + 1 when you want a list numbered from 1. The unpacking works exactly like let (name, age) = pet on a tuple.

    If you prefer not to unpack, each item is a tuple with the labels offset and element: for pair in fruits.enumerated() lets you write pair.offset and pair.element. Unpacking into your own names is usually clearer, because (i, fruit) says what each part is.

    Walking two arrays side by side

    zip(a, b) pairs the first item of a with the first item of b, then the second items, and so on. Each pair is a tuple, and the loop unpacks it:

    let prices = [3, 1, 2]
    for (fruit, price) in zip(fruits, prices) {
        print("\(fruit) costs \(price)")
    }
    
    apple costs 3
    kiwi costs 1
    plum costs 2
    

    Two details trip people up:

    • zip is a function, not a method. Write zip(fruits, prices). fruits.zip(prices) fails with "value of type '[String]' has no member 'zip'".
    • zip stops at the shorter array. The extra items of the longer one are skipped, with no error. zip(fruits, [3, 1]) gives only the pairs for apple and kiwi.

    To see what zip builds, turn it into an array: Array(zip(fruits, prices)) is [("apple", 3), ("kiwi", 1), ("plum", 2)], a list of tuples. The loop simply unpacks one tuple per pass. Compared with an index loop, there is no prices[i] to get wrong, and no risk of running past the end of the shorter array.

    Using both together

    The two work together. zip(fruits, prices).enumerated() gives a count and a pair at each step, and the names nest the same way:

    for (i, (fruit, price)) in zip(fruits, prices).enumerated() {
        print("\(i + 1). \(fruit) costs \(price)")
    }
    
    1. apple costs 3
    2. kiwi costs 1
    3. plum costs 2
    

    The inner parentheses match the inner tuple: the count is outside, and the pair is inside.

    The lesson's exercise

    The array players holds names, and scores holds their points in the same order.

    1. Numbered list. Loop over players.enumerated(), unpacking each item into (i, player), and print "\(i + 1). \(player)". The count starts at 0, so adding 1 makes Ana number 1.
    2. Players with points. Loop over zip(players, scores), unpacking each pair into (player, points), and print "\(player) has \(points) points". No index is needed, because zip already matched Ana with 12, Ben with 9 and Cleo with 15.
    class Solution {
        func mainFunction() {
            let players = ["Ana", "Ben", "Cleo"]
            let scores = [12, 9, 15]
            for (i, player) in players.enumerated() {
                print("\(i + 1). \(player)")
            }
            for (player, points) in zip(players, scores) {
                print("\(player) has \(points) points")
            }
        }
    }
    

    The output is:

    1. Ana
    2. Ben
    3. Cleo
    Ana has 12 points
    Ben has 9 points
    Cleo has 15 points
    

    Common mistakes

    • Names in the wrong order. In enumerated() the count comes first. for (player, i) in ... would put the count into player.
    • Forgetting the + 1. A list numbered from 0 looks like a mistake to the reader and to the lesson's tests.
    • Forgetting the second pair of parentheses when combining the two. for (i, fruit, price) in ... is a compile error, because the items are a count and a pair, not three values.

    Key takeaways

    • enumerated() gives (count, item), counting from 0.
    • zip(a, b) gives pairs (itemFromA, itemFromB) and stops at the shorter array.
    • Nest the tuple names to combine them: (i, (a, b)).
    Keep going with Swift500+ step-by-step lessons, from your first line of code to coding interviews. Free to start.
    Start learning free