Scala FAQ: How do I append or prepend one or more elements to a Vector or Seq class?
Solution
To append or prepend one or more elements to a Vector
or Seq
, use these methods:
- to append one item, use
:+
- to append multiple items, use
++
- to prepend one item, use
+:
- to prepend multiple items, use
++:
In tabular form that looks like this:
Need | Method |
---|---|
append 1 item | oldSeq :+ e |
append multiple items | oldSeq ++ newSeq |
prepend 1 item | e +: oldSeq |
prepend multiple items | newSeq ++: oldSeq |
Remember that Vector
and Seq
are immutable, so you can’t modify them. Therefore, during the append or prepend operations, you need to assign the result to a new variable.
Example data
In the examples that follow, I’ll always begin with this variable:
scala> val a = Vector(1, 2, 3)
a: scala.collection.immutable.Vector[Int] = Vector(1, 2, 3)
Append a single item
This is how you append a single item to a Vector
:
scala> val b = a :+ 4
b: scala.collection.immutable.Vector[Int] = Vector(1, 2, 3, 4)
Notice that it uses the :+
method.
Append multiple elements
To append multiple elements to a Vector
, use the ++
method:
scala> val b = a ++ Vector(4, 5)
b: scala.collection.immutable.Vector[Int] = Vector(1, 2, 3, 4, 5)
Prepend a single item
To prepend a single item to a Vector
, use the +:
method:
scala> val b = 0 +: a
b: scala.collection.immutable.Vector[Int] = Vector(0, 1, 2, 3)
Prepend multiple elements
To prepend multiple elements to a Vector
, use the ++:
method:
scala> val b = Seq(-1, 0) ++: a
b: scala.collection.immutable.Vector[Int] = Vector(-1, 0, 1, 2, 3)
Seq works just like Vector
Though I only showed a Seq
in the last example, it uses the same append and prepend methods as the Scala Vector
class.
How to remember the method names
One way I remember the method names is to think that the :
represents the side that the sequence is on, so when I use +:
, I know that the sequence needs to be on the right, like this:
0 +: a
A more accurate way to think about the method names is that a Scala method name that ends with the :
character is right-associative, meaning that the method comes from the variable on the right side of the expression. Therefore, in these examples, the methods actually come from the variable a
on the far right side of the expression:
0 +: a
Seq(-1, 0) ++: a
In the other examples, the method comes from the variable a
, which is on the left:
val b = a :+ 4
val b = a ++ Vector(4, 5)
Because you know that these methods come from the Vector
and Seq
classes, if you think about this associativity, you will always get the :
character on the correct side.
In the last example I demonstrate
++
, which is used consistently across the immutable collections classes.
A possible problem
Although I haven’t done this in production code, I just noticed that you can use the :+
and +:
methods in a way that most likely won’t give you what you want:
// INTENTIONAL ERROR
scala> a :+ Seq(4,5)
res0: scala.collection.immutable.Vector[Any] = Vector(1, 2, 3, List(4, 5))
-------------------
// INTENTIONAL ERROR
scala> a +: Seq(4,5)
res1: Seq[Any] = List(Vector(1, 2, 3), 4, 5)
---------------------
That usage might make sense with other sequential collections, but at the moment it looks like a potential cause of error. Because those methods treat the variable they’re appending/prepending as a single element, you end up with a sequence inside a sequence, which again is probably not what you want.