How to populate Scala collections with a Range

This is an excerpt from 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 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))

That sequence 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)

The Scala Cookbook

This tutorial is sponsored by the Scala Cookbook, which I wrote for O’Reilly:

You can find the Scala Cookbook at these locations:

Add new comment

The content of this field is kept private and will not be shown publicly.

Anonymous format

  • Allowed HTML tags: <em> <strong> <cite> <code> <ul type> <ol start type> <li> <pre>
  • Lines and paragraphs break automatically.
By submitting this form, you accept the Mollom privacy policy.