Start learning free

LESSON 104 OF 414 · ARRAYS I

Array Pop in Scala: Removing from an ArrayBuffer

Lesson Read the full explanation

With scala.collection.mutable.ArrayBuffer, we can remove an element at an index using remove(index).

val arr = scala.collection.mutable.ArrayBuffer(1, 4, 6)
arr.remove(1)

// arr is now ArrayBuffer(1, 6)

Assignment
Follow the Coding Tutorial and remove an item.


Hint
Use remove(index).


STEP 1 OF 2
    Ctrl + Enter to check

    SCALA · ARRAYS I

    Array Pop in Scala, explained

    Removing by index

    Many languages have a pop that removes the last element of an array. In Scala, an ArrayBuffer (from scala.collection.mutable, written with its full name in the lesson) has remove(index), which deletes the element at an index. The buffer shrinks by one, and the elements after the removed one shift to the left.

    val arr = scala.collection.mutable.ArrayBuffer(1, 4, 6)
    arr.remove(1)
    
    println(arr)   // ArrayBuffer(1, 6)
    

    remove also returns the element it deleted, so you can keep it:

    val fruits = scala.collection.mutable.ArrayBuffer("mango", "kiwi", "grapefruit")
    val removed = fruits.remove(2)
    
    println(removed)   // grapefruit
    println(fruits)    // ArrayBuffer(mango, kiwi)
    

    When the returned value isn't needed, as in the lesson, it is simply ignored.

    Removing the last item

    Because indices run from 0 to size - 1, the last element sits at index size - 1. So "pop" is written as:

    buffer.remove(buffer.size - 1)
    

    The expression buffer.size - 1 is evaluated before the removal, using the current size, so the same line works no matter how long the buffer is.

    What happens to the other elements

    Removing from the end is the cheap case: nothing needs to move. Removing from the front or the middle shifts every later element one place to the left, so the indices of those elements change. After remove(0) on ArrayBuffer(14, 32, 50, 21), the value 32 is at index 0 and the buffer is ArrayBuffer(32, 50, 21). Keep that in mind if you remove inside a loop over the same buffer: the indices move under you.

    The exercise

    The lesson starts with two buffers:

    val fruits = scala.collection.mutable.ArrayBuffer("mango", "kiwi", "grapefruit")
    val ages = scala.collection.mutable.ArrayBuffer(14, 32, 50, 21)
    
    1. Remove the last fruit. The last index is fruits.size - 1, which is 2, so "grapefruit" goes and two fruits remain.
    2. Remove the last two ages. The first call removes 21 at index 3. Now the buffer holds three elements, so the same expression ages.size - 1 gives 2 and the second call removes 50. Writing the index as an expression rather than a fixed number is what lets the same line work twice.
    val fruits = scala.collection.mutable.ArrayBuffer("mango", "kiwi", "grapefruit")
    val ages = scala.collection.mutable.ArrayBuffer(14, 32, 50, 21)
    
    fruits.remove(fruits.size - 1)
    ages.remove(ages.size - 1)
    ages.remove(ages.size - 1)
    

    Afterwards fruits is ArrayBuffer(mango, kiwi) and ages is ArrayBuffer(14, 32).

    Removing several or by value

    Two related operations come up often. remove(index, count) deletes count elements starting at index, and -= deletes the first element equal to a given value:

    val a = scala.collection.mutable.ArrayBuffer(1, 2, 3, 4)
    a.remove(1, 2)       // deletes the elements at indices 1 and 2
    println(a)           // ArrayBuffer(1, 4)
    
    val b = scala.collection.mutable.ArrayBuffer(1, 2, 3, 2)
    b -= 2               // only the first 2 is removed
    println(b)           // ArrayBuffer(1, 3, 2)
    

    Mistakes to avoid

    • Using fruits.size as the index. It is one past the last element, and remove throws an IndexOutOfBoundsException.
    • Removing from an empty buffer. The expression size - 1 is then -1, and remove(-1) throws an IndexOutOfBoundsException. Check buffer.nonEmpty first when the buffer might be empty.
    • Confusing index and value. ages.remove(21) removes the element at index 21, not the value 21, and fails on a short buffer. To remove a value, use -=: ages -= 21 deletes the first element equal to 21.
    • Trying it on a List or an Array. A List is immutable, and an Array has a fixed size, so neither has an in-place remove. Use an ArrayBuffer, or build a new collection, for example list.init, which is the list without its last element.

    Key takeaways

    • buffer.remove(i) deletes the element at index i, shifts the rest left and returns the removed element.
    • The last element is at buffer.size - 1.
    • Removing from an empty buffer throws, so guard against it.
    • -= removes by value, remove removes by index.
    Keep going with ScalaAbout 340 step-by-step lessons, from your first line of code to coding interviews. Free to start.
    Start learning free