Scala - Ranges



In Scala, Range is an ordered sequence of integers. Range can have start and endpoints. Range is part of the collection. You can use range of built-in functions in Scala. Range is an organized series of integers.

Creating Range

You can create range for negative, positive and decimal values. Ranges are ordered datatype in Scala. You can use filter, map and foreach functions to use range. You can create ranges in various ways as explained below.

1. Using Companion Object

You can provide start and endpoint for a range. You can use the Range.inclusive method to do this. For example,

val rangeInclByTwo = Range.inclusive(1, 10, 2)
rangeInclByTwo.toList shouldBe List(1, 3, 5, 7, 9)

The output will be List(1, 3, 5, 7, 9). It is starting from 1 and ends in 10 with step size is 2.

Another code will be,

val rangeExclStepTwo = Range(1, 10, 2)
rangeExclStepTwo.toList shouldBe List(1, 3, 5, 7, 9)

Note that there is a difference between these codes. First code has rangeInclByTwo and second code has rangeExclStepTwo. It means the first one has an inclusive range and the second one has an exclusive range.

2. Using to and until methods

You can use until and methods to define ranges. For example,

val rangeToStepThree = 1 to 10 by 3
rangeToStepThree.toList shouldBe List(1, 4, 7, 10)

The output will be List(1, 4, 7, 10)

This code is the same as Range.inclusive(1, 10, 3). You can also give range by using until. For example,

val rangeUntilStepTwo = 1 until 10 by 2
rangeUntilStepTwo.toList shouldBe List(1, 3, 5, 7, 9)

The output will be List(1, 3, 5, 7, 9)

3. Range with Step

The default step is 1 while creating ranges in Scala. It means the difference of two consecutive values will be 1. You can also set step size while defining ranges in Scala. You can use by keyword to set step size in range. For example,

val evenRange = 2 to 100 by 2
evenRange.head shouldBe 2
evenRange.last shouldBe 100

The output will be,

evenRange.head // Output: 2
evenRange.last // Output: 100

You can also use companion objects to set step size while creating ranges. For example,

val rangeStepByThree = Range(1, 10, 3)
rangeStepByThree.toList shouldBe List(1, 4, 7)

The output will be List(1, 4, 7)

You can set step size as a negative value too. For example,

val reverseRangeFrom10 = 10 to 1 by -2
reverseRangeFrom10.head shouldBe 10
reverseRangeFrom10.last shouldBe 2

The output will be,

reverseRangeFrom10.head // Output: 10
reverseRangeFrom10.last // Output: 2

The variable will contain even numbers from 10 to 2 in descending order.

Note that if you set the positive step size in reverseRangeFrom10 then it will be empty. It is not possible to start from 10 with step size 2 and end with 2. It will never reach the end point.

You can also create a range of negative numbers. For example,

val negativeRangeByThree = -1 to -10 by -3
negativeRangeByThree.toList shouldBe List(-1, -4, -7, -10)

The output will be List(-1, -4, -7, -10)

Note that if you set positive step size. Then it will never reach the end point because you can reach to -10 from starting from -1 while adding positive step size every time.

4. Non-Integer Range

We discussed ranges with Integers. Now, we will explain ranges with decimal numbers in this section. You need to set step size explicitly for decimal numbers. There is no default step size in case of decimal numbers.

For example,

val tripleRange = 1.5 to 2.5 by 0.3
println(tripleRange.toList)

The output will be List(1.5, 1.8, 2.1, 2.4). But starting from Scala 2.12.6, it is not recommended to create range in this way. It is because of problems with approximating decimal points. You can use BiDecimal instead of Double to create such ranges in Scala.

For example,

val customDecimalRange = BigDecimal(0.5) to BigDecimal(1.5) by 0.25
customDecimalRange shouldBe List(0.5, 0.75, 1.0, 1.25, 1.5)

The output will be List(0.5, 0.75, 1.0, 1.25, 1.5)

Useful Methods on Range

The methods that work with collections can also be used with ranges. We will discuss some of them here.

(a) Iterate and Filter

There are various iterates available like filter, filternot, map and foreach. You can use these in ranges. These methods are inherited from trait TraversableLike. You can use the toList function to convert a range into a list.

val customRange = 5 to 15

val multiplesOfThree = customRange.filter(_ % 3 == 0)
multiplesOfThree shouldBe List(6, 9, 12, 15)

val squaredValues = customRange.map(n => n * n)
squaredValues shouldBe List(25, 36, 49, 64, 81, 100, 121, 144, 169, 196)

(b) Take and Drop

Range has methods like, take, takeWhile, drop, dropWhile etc. These methods return another range.

val customRange = 5 to 15

val takeThree: Range = customRange.take(3)
takeThree.head shouldBe 5
takeThree.last shouldBe 7

val dropTwo: Range = customRange.drop(2)
dropTwo.head shouldBe 7
dropTwo.last shouldBe 15

Conclusion

Ranges are generally used in the loops and iteration. Range has three constraints, i.e, start, end, and step size. Ranges are immutable and part of collections in Scala. You can create various sequences and series of integers and decimal numbers. Range provides faster execution.

Advertisements