How to populate Scala collections with a Range

This is an excerpt from the 1st Edition of the Scala Cookbook (partially modified for the internet). This is Recipe 10.25, “How to Populate a Scala Collection with a Range”

Problem

You want to populate a Scala List, Array, Vector, or other sequence with a Range.

Solution

Call the range method on Scala sequence classes that support it, or create a Range and convert it to the desired sequence.

In the first approach, the range method is available on the companion object of supported types like Array, List, Vector, ArrayBuffer, and others:

scala> Array.range(1, 5)
res0: Array[Int] = Array(1, 2, 3, 4)

scala> List.range(0, 10)
res1: List[Int] = List(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)

scala> Vector.range(0, 10, 2)
res2: collection.immutable.Vector[Int] = Vector(0, 2, 4, 6, 8)

For some of the collections, such as List and Array, you can also create a Range and convert it to the desired sequence:

scala> val a = (0 until 10).toArray
a: Array[Int] = Array(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)

scala> val list = 1 to 10 by 2 toList
list: List[Int] = List(1, 3, 5, 7, 9)

scala> val list = (1 to 10).by(2).toList
list: List[Int] = List(1, 3, 5, 7, 9)

The REPL shows the collections that can be created directly from a Range:

toArray    toBuffer        toIndexedSeq   toIterable   toIterator
toList     toMap           toSeq          toSet        toStream
toString   toTraversable

Using this approach is useful for some collections, like Set, which don’t offer a range method:

// intentional error
scala> val set = Set.range(0, 5)
<console>:7: error: value range is not a member of object
scala.collection.immutable.Set
       val set = Set.range(0,5)
                     ^

scala> val set = (0 until 10 by 2).toSet
set: scala.collection.immutable.Set[Int] = Set(0, 6, 2, 8, 4)

You can also use a Range to create a sequence of characters:

scala> val letters = ('a' to 'f').toList
letters: List[Char] = List(a, b, c, d, e, f)

scala> val letters = ('a' to 'f').by(2).toList
letters: List[Char] = List(a, c, e)

As shown in many recipes, ranges are also very useful in for loops:

scala> for (i <- 1 until 10 by 2) println(i)
1
3
5
7
9

Discussion

By using the map method with a Range, you can create a sequence with elements other than type Int or Char:

scala> val map = (1 to 5).map(_ * 2.0)
map: collection.immutable.IndexedSeq[Double] = Vector(2.0, 4.0, 6.0, 8.0, 10.0)

Using a similar approach, you can also return a sequence of Tuple2 elements:

scala> val map = (1 to 5).map(e => (e,e))
map: scala.collection.immutable.IndexedSeq[(Int, Int)] = Vector((1,1), (2,2), (3,3), (4,4), (5,5))

A nice thing about that approach is that it easily converts to a Map:

scala> val map = (1 to 5).map(e => (e,e)).toMap
map: scala.collection.immutable.Map[Int,Int] = Map(5 -> 5, 1 -> 1, 2 -> 2, 3 -> 3, 4 -> 4)