Start learning free

LESSON 150 OF 414 · LOOPING OVER ARRAY INDICES

Looping Through Arrays with Indices in Scala

Lesson Read the full explanation

In some instances, we will want to loop through an array using indices.

The indices of an array meals are all the integer values from 0 to meals.length - 1, so we can iterate over them using an index variable i:

val meals = Array("pancakes", "pasta", "pizza", "avocado")

for (i <- meals.indices) {
	println("Meal number " + (i + 1) + " is " + meals(i) + ".")
}

The output of this code is:

Meal number 1 is pancakes.
Meal number 2 is pasta.
Meal number 3 is pizza.
Meal number 4 is avocado.

Assignment
Now let's print the temperature on each day, in this format:

On day 1 the temperature is 10.

On day 2 the temperature is 60.

...


Hint
Look at the examples above if you get stuck.


STEP 1 OF 2
    Ctrl + Enter to check

    SCALA · LOOPING OVER ARRAY INDICES

    Looping Through Arrays With Indices in Scala, explained

    When you need the index

    Most array loops in Scala use the elements directly: for (x <- array) gives you each value in turn. That loop doesn't tell you where in the array you are. Sometimes the position matters. You may want to print "item number 3", compare each element with the one before it, change elements in place, or return the position of a match. For those jobs you loop over the indices, the positions themselves, and read each element with its index.

    Indices and ranges

    An array of n elements has the indices 0 through n - 1. The first element is at index 0 and the last is at index size - 1. Scala reads an element with parentheses, meals(2), not with square brackets.

    Scala builds the sequence of indices with a range. There are two range operators, and the difference is whether the upper end is included:

    • 0 until n stops before n: 0, 1, ..., n - 1. This is the range of valid indices.
    • 0 to n includes n: 0, 1, ..., n. As an index range it is one step too long.

    An array also provides its index range ready-made as indices, so for (i <- meals.indices) and for (i <- 0 until meals.size) visit the same positions. The property size gives the number of elements, and length gives the same number.

    An example

    val meals = Array("pancakes", "pasta", "pizza", "avocado")
    
    for (i <- meals.indices) {
        println("Meal number " + (i + 1) + " is " + meals(i) + ".")
    }
    

    The output is:

    Meal number 1 is pancakes.
    Meal number 2 is pasta.
    Meal number 3 is pizza.
    Meal number 4 is avocado.
    

    Indices start at 0, but people count from 1. That is why the code prints i + 1. The parentheses matter: "Day " + x + 1 with x = 5 builds the text Day 51, because each + appends text from left to right. "Day " + (x + 1) adds first and gives Day 6.

    The exercise: the temperature on each day

    The lesson gives an array temperatures and asks for one line per day, in the form On day 1 the temperature is 10. The two steps are:

    1. Loop over the indices. Use a variable i and the range 0 until temperatures.size. The until keeps i from reaching temperatures.size, which is one past the last valid index.
    2. Print the line inside the loop with an s"..." string. The s in front of the quotes turns on string interpolation: a ${...} inside the string is replaced by the value of the expression in the braces. The day is ${i + 1} and the temperature is ${temperatures(i)}.
    val temperatures = Array(10, 60, -5, 32)
    
    for (i <- 0 until temperatures.size) {
        println(s"On day ${i + 1} the temperature is ${temperatures(i)}.")
    }
    

    The output is:

    On day 1 the temperature is 10.
    On day 2 the temperature is 60.
    On day 3 the temperature is -5.
    On day 4 the temperature is 32.
    

    More things the index lets you do

    With the index you can write to the array, since arrays in Scala are mutable. temperatures(i) = temperatures(i) * 2 replaces the element at position i. You can also walk backwards with temperatures.indices.reverse, skip positions with 0 until temperatures.size by 2, or compare neighbours. A loop that starts at 1 can read the element before the current one:

    for (i <- 1 until temperatures.size) {
        println(temperatures(i) - temperatures(i - 1))
    }
    

    For Array(10, 60, -5, 32) this prints 50, -65 and 37. It starts at 1 because index 0 has no previous element.

    Common mistakes

    • Using to instead of until. The loop for (i <- 0 to temperatures.size) runs once too often. On the last pass temperatures(4) asks for an element that doesn't exist, and the program stops with java.lang.ArrayIndexOutOfBoundsException: Index 4 out of bounds for length 4.
    • Starting at 1. That skips the first element.
    • Printing i where you mean i + 1. The first day would be "day 0".
    • Square brackets. temperatures[i] is not how Scala reads an element. Use temperatures(i).
    • An empty array. 0 until 0 is an empty range, so the loop body never runs and nothing is printed.

    Key takeaways

    • The valid indices of an array are 0 through size - 1.
    • 0 until temperatures.size and temperatures.indices produce exactly those indices.
    • Use to when you want the upper end included and until when you don't.
    • Read an element with array(i) and write one with array(i) = value.
    • Loop over the indices when the position matters, and over the elements when it doesn't.
    Keep going with ScalaAbout 340 step-by-step lessons, from your first line of code to coding interviews. Free to start.
    Start learning free