Start learning free

LESSON 113 OF 677 · ARRAYS I

Insert and Remove at a Position in Scala

Lesson Read the full explanation

TL ; DR:

insert(i, x) puts x at index i. Use remove(i) to take out the item at index i. The other items move to make room or to close the gap.


val colors = scala.collection.mutable.ArrayBuffer("red", "green", "blue")

colors.insert(1, "pink")
println(colors)   // ArrayBuffer(red, pink, green, blue)

colors.remove(0)
println(colors)   // ArrayBuffer(pink, green, blue)


Full lesson:

+= adds an item at the end. To put one anywhere else in an ArrayBuffer, use insert(i, x). The items from index i on move one place to the right.

val pets = scala.collection.mutable.ArrayBuffer("Rex", "Milo")
pets.insert(0, "Luna")
println(pets)   // ArrayBuffer(Luna, Rex, Milo)

You met remove(i) in the last lesson. It takes out the item at index i. The items after it move one place to the left. It also returns the item:

val first = pets.remove(0)
println(first)   // Luna
println(pets)    // ArrayBuffer(Rex, Milo)

Watch the indexes. After an insert or a removal, the items behind that spot have new indexes.

Both take the index first. The -= operator is different: it takes out a value, not an index.


Your task

pets holds the pets waiting at the vet, in order.

Bella has an appointment, so she goes second, at index 1. Then Milo goes home. Take him out of the line.

The code below prints how many pets wait once Bella is in. At the end, it prints the pets left.

Expected output:

4
Rex Bella Luna
STEP 1 OF 2
    Ctrl + Enter to check

    SCALA · ARRAYS I

    Array Insert Remove in Scala, explained

    Adding and removing in the middle

    An ArrayBuffer is Scala's growable list. += adds an item at the end, but sometimes an item has to go somewhere else, or leave from somewhere else. Two methods do that, and both take an index first:

    • insert(i, x) puts x at index i. The items from index i on move one place to the right.
    • remove(i) takes out the item at index i. The items after it move one place to the left, closing the gap.
    val colors = scala.collection.mutable.ArrayBuffer("red", "green", "blue")
    
    colors.insert(1, "pink")
    println(colors)   // ArrayBuffer(red, pink, green, blue)
    
    colors.remove(0)
    println(colors)   // ArrayBuffer(pink, green, blue)
    

    Both methods change the buffer itself. They don't build a new one.

    remove also returns the item

    remove(i) hands back the item it took out, so you can keep it:

    val pets = scala.collection.mutable.ArrayBuffer("Rex", "Milo")
    pets.insert(0, "Luna")
    println(pets)    // ArrayBuffer(Luna, Rex, Milo)
    
    val first = pets.remove(0)
    println(first)   // Luna
    println(pets)    // ArrayBuffer(Rex, Milo)
    

    If you don't need the item, ignore the result, as the lesson's task does.

    Indexes shift

    After an insert or a removal, every item behind that spot has a new index. This is the usual source of mistakes. In Rex, Milo, Luna, Milo is at index 1. Once Bella is inserted at index 1, Milo is at index 2. A remove(1) written from memory of the old list would take out Bella.

    The end is a valid index for insert

    You can insert at index size, which puts the item at the end. A larger index is an error: inserting at index 10 into a three-item buffer throws an IndexOutOfBoundsException. So does remove(5) on a buffer that has fewer than six items.

    An index is not a value

    -= also removes, but it takes a value, not an index. The two look alike on a buffer of numbers, and they give different results:

    val nums = scala.collection.mutable.ArrayBuffer(10, 20, 30, 40)
    nums.remove(1)    // index 1: removes 20
    println(nums)     // ArrayBuffer(10, 30, 40)
    
    nums -= 10        // value 10: removes the item that equals 10
    println(nums)     // ArrayBuffer(30, 40)
    

    With strings, pets -= "Milo" removes the first item equal to "Milo" and does nothing if there is none.

    Why the shifting matters

    An ArrayBuffer keeps its items in one row, numbered from 0 with no gaps. When you insert, the buffer has to open a gap, so every item from that index on slides one place right. When you remove, it closes the gap, so every item behind slides one place left. That is why a long buffer is slower to change near its front than near its end, and why the numbers you had in mind a moment ago can be wrong a line later. When a task has several steps, work out the buffer after each call and read the new indexes from that.

    The task

    The vet's line starts as Rex, Milo, Luna. Bella has an appointment and goes second, at index 1. Then Milo goes home. The code prints how many pets wait once Bella is in, and at the end it prints the pets left.

    1. Call pets.insert(1, "Bella"). The line is now Rex, Bella, Milo, Luna.
    2. Milo moved from index 1 to index 2, so call pets.remove(2).
    val pets = scala.collection.mutable.ArrayBuffer("Rex", "Milo", "Luna")
    pets.insert(1, "Bella")
    println(pets.size)
    pets.remove(2)
    println(pets(0) + " " + pets(1) + " " + pets(2))
    

    It prints:

    4
    Rex Bella Luna
    

    Key takeaways

    • insert(i, x) adds x at index i and shifts the rest to the right; the index comes first.
    • remove(i) takes out the item at index i, shifts the rest to the left and returns the item.
    • After either call, recompute the indexes of the items behind that spot.
    • -= removes by value; remove removes by index.
    Keep going with Scala500+ step-by-step lessons, from your first line of code to coding interviews. Free to start.
    Start learning free