Start learning free

LESSON 226 OF 677 · LOOPS WITH STRINGS, ARRAYS & DICTIONARIES

Looping Over a Dictionary in Scala: for with (key, value)

Lesson Read the full explanation

TL ; DR:

A for loop over a Map visits every entry. (fruit, amount) splits each one into its key and its value.


val stock = scala.collection.mutable.Map("apples" -> 5, "pears" -> 2)

for ((fruit, amount) <- stock) {
    println(s"$fruit $amount")
}

// pears 2
// apples 5   (in any order)


Full lesson:

A loop can visit every entry of a map, one at a time. The loop body runs once per key.

Mind the double parentheses. The outer pair belongs to the for. The inner pair splits the entry into the key and the value.

Loop over stock.keys to get only the keys.

Don't need the key? Write _ in its place, as in for ((_, amount) <- stock).

The order: a mutable Map has no fixed order. The entries may come in any order. A total or a count comes out the same in any order. Those are safe answers.


Your task

A game keeps each player's points in scores. The variables total and count start at 0.

Loop over scores. Add every player's points to total. Count the players with 10 points or more in count.

The loop needs only the points, not the names. The code at the bottom prints both.

Expected output:

43
2
STEP 1 OF 3
    Ctrl + Enter to check

    SCALA · LOOPS WITH STRINGS, ARRAYS & DICTIONARIES

    Looping Over Dictionaries in Scala, explained

    What the loop does

    A Map holds pairs: each key has one value. A for loop over a map runs its body once per entry, and each entry is a pair. Writing (fruit, amount) in front of <- splits the pair into two names, so the body can use the key and the value separately.

    val stock = scala.collection.mutable.Map("apples" -> 5, "pears" -> 2)
    
    for ((fruit, amount) <- stock) {
        println(s"$fruit $amount")
    }
    

    This prints two lines, pears 2 and apples 5. Another run or another Scala version may print them the other way round.

    Double parentheses

    There are two pairs of parentheses, and they do different jobs. The outer pair belongs to the for. The inner pair, (fruit, amount), takes one entry apart. Without the inner pair, for (entry <- stock) still works, but then entry is the whole pair, written (pears,2) when printed, and you would need entry._1 and entry._2 to reach the parts.

    Only the keys, or only the values

    To visit only the keys, loop over stock.keys:

    for (k <- stock.keys) {
        println(k)
    }
    

    When you need the values but not the keys, put _ where the key would be: for ((_, amount) <- stock). The underscore means "there is a key here, and I don't use it".

    The order is not fixed

    A mutable Map makes no promise about the order of its entries. The loop may visit them in an order that differs from the order you added them in. So write loops whose result does not depend on the order. A total, a count and a yes-or-no check give the same answer however the entries come. Printing line by line, or "the first entry", does not.

    The exercise

    The map scores holds each player's points, and the variables total and count start at 0. The task is to add every player's points to total, and count the players with 10 points or more in count. Only the points matter, so the key is skipped.

    1. Write the loop with (_, points), and its closing brace right away.
    2. Inside it, add points to total.
    3. Still inside, if points is 10 or more, add 1 to count.
    val scores = scala.collection.mutable.Map("Ana" -> 12, "Ben" -> 7, "Cleo" -> 15, "Dan" -> 9)
    var total = 0
    var count = 0
    
    for ((_, points) <- scores) {
        total += points
        if (points >= 10) {
            count += 1
        }
    }
    
    println(total)
    println(count)
    

    It prints 43 and 2: 12 + 7 + 15 + 9 is 43, and only Ana and Cleo have 10 or more. Both numbers are the same whichever order the loop visits the players in.

    Common mistakes

    • Writing for (fruit, amount <- stock) with one pair of parentheses. The inner pair is needed to split the entry.
    • Declaring total with val. It changes inside the loop, so it must be var.
    • Counting players inside a check that is placed outside the loop, so it runs once instead of once per player.
    • Relying on the order of the entries for anything other than a total, a count or a check.

    Key takeaways

    • for ((key, value) <- map) visits every entry and splits it into its two parts.
    • map.keys gives only the keys; _ skips a part you don't need.
    • A mutable map has no fixed order, so use loops whose answer doesn't depend on it.
    Keep going with Scala500+ step-by-step lessons, from your first line of code to coding interviews. Free to start.
    Start learning free