Start learning free

LESSON 275 OF 677 · PAIRS, SORTING & BUILT-INS

withIndex and zip in Kotlin: Loops with Positions and Pairs

Lesson Read the full explanation

TL ; DR:

withIndex() gives each item with its index. zip walks two lists side by side.


val fruits = mutableListOf("apple", "kiwi", "plum")
val prices = mutableListOf(3, 1, 2)

for ((i, fruit) in fruits.withIndex()) {
    println("${i + 1}. $fruit")    // 1. apple, then 2. kiwi, then 3. plum
}

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


Full lesson:

You have looped with for (i in 0 until meals.size). Then meals[i] gave the item. Kotlin has a shorter way to get both.

withIndex() gives each item together with its index. The loop unpacks the two, as val (name, age) = pet unpacks a pair.

for ((i, meal) in meals.withIndex()) {
    println("$i $meal")
}

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

a.zip(b) walks two lists 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. The result is a list of Pairs.

for ((fruit, price) in fruits.zip(prices)) {
    println("$fruit costs $price")
}

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

The two work together. fruits.zip(prices).withIndex() gives an index and a pair each time.

Watch out here. A for line can't unpack a pair inside a pair. Unpack the pair on the loop's first line instead.

for ((i, pair) in fruits.zip(prices).withIndex()) {
    val (fruit, price) = pair
    println("${i + 1}. $fruit costs $price")
}

Your task

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

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

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

    KOTLIN · PAIRS, SORTING & BUILT-INS

    Enumerate And Zip in Kotlin, explained

    Why these two exist

    You have looped over positions with for (i in 0 until meals.size) and then read meals[i] to get the item. Kotlin has a shorter way to get both the position and the item, and another for walking two lists together.

    withIndex()

    withIndex() gives each item together with its index. The loop unpacks the two parts, the same way val (name, age) = pet unpacks a pair:

    val fruits = listOf("apple", "kiwi", "plum")
    for ((i, fruit) in fruits.withIndex()) {
        println("$i $fruit")
    }
    
    0 apple
    1 kiwi
    2 plum
    

    The index comes first and starts at 0. For a numbered list that starts at 1, print i + 1: println("${i + 1}. $fruit") gives 1. apple, then 2. kiwi, then 3. plum.

    zip

    a.zip(b) walks two lists side by side. It pairs the first item of a with the first item of b, then the second items, and so on. The result is a list of Pairs, which the loop unpacks:

    val prices = listOf(3, 1, 2)
    for ((fruit, price) in fruits.zip(prices)) {
        println("$fruit costs $price")
    }
    
    apple costs 3
    kiwi costs 1
    plum costs 2
    

    zip stops at the end of the shorter list. With two prices instead of three, fruits.zip(listOf(3, 1)) is [(apple, 3), (kiwi, 1)]: the extra fruit is skipped, with no error.

    Using both together

    fruits.zip(prices).withIndex() gives an index and a pair on each pass. A for line can't unpack a pair inside a pair: writing for ((i, (fruit, price)) in ...) is a syntax error. Unpack the pair on the first line of the loop's body:

    for ((i, pair) in fruits.zip(prices).withIndex()) {
        val (fruit, price) = pair
        println("${i + 1}. $fruit costs $price")
    }
    
    1. apple costs 3
    2. kiwi costs 1
    3. plum costs 2
    

    The exercise

    A quiz show keeps its players in players and their points in scores, in the same order. First print the players as a numbered list from 1, with withIndex(). Then print each player with their points, with zip.

    class Solution {
        fun mainFunction() {
            val players = mutableListOf("Ana", "Ben", "Cleo")
            val scores = mutableListOf(12, 9, 15)
    
            for ((i, player) in players.withIndex()) {
                println("${i + 1}. $player")
            }
    
            for ((player, points) in players.zip(scores)) {
                println("$player has $points points")
            }
        }
    }
    

    The output:

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

    The first loop needs the position, so it uses withIndex(). The second needs the matching score, not the position, so zip is enough and no index is involved.

    Why does withIndex() exist when you can write meals[i]? With a plain index loop it is easy to make a slip, such as going one step past the last item. withIndex() only hands you items that exist. It also works on any list the same way, and the loop says plainly that it needs both the position and the value.

    Likewise, zip saves you from indexing two lists with the same i. Instead of players[i] and scores[i] in one loop, the pair arrives ready: the first name goes with the first score, and so on. The two lists must be kept in the same order for this to be right, which the exercise promises.

    Common mistakes

    • Printing i instead of i + 1, so the list starts at 0.
    • Swapping the unpacked names. In (i, player) the index is first. Writing (player, i) compiles for withIndex(), but player then holds a number.
    • Lists of different lengths in zip. The longer list's extra items are dropped silently, so check the lengths if that matters.

    Key takeaways

    • withIndex() gives (index, item), with the index first, from 0.
    • a.zip(b) pairs items by position and stops at the shorter list.
    • To combine them, unpack the inner pair in a separate line.
    Keep going with Kotlin500+ step-by-step lessons, from your first line of code to coding interviews. Free to start.
    Start learning free