Ruby Tutorial Ruby References

Ruby - Ranges



A range represents an interval, a set of values with a beginning and an end. Values of a range can be numbers, characters, strings or objects. It is constructed using double dot (..) operator, triple dot (...) operator or ::new method. It provides flexibility to the code and reduce the size of code.

Ruby supports ranges to be used in a variety of ways.

  • Ranges as Sequences
  • Ranges as Conditions
  • Ranges as Intervals

Ranges as Sequences

The most natural way to use ranges in Ruby is to produce successive values in the sequence. Sequence has a start point, an end point, and a way to produce successive values in the sequence. There are three most commonly used method for constructing ranges.

  • (..) operator : Creates a range from start point to end point inclusive.
  • (...) operator : Creates a range from start point to end point exclusive.
  • ::new method : Creates a range from start point to end point.
#(..) operator
(-1..-5)         #=> []
(-5..-1)         #=> [-5, -4, -3, -2, -1]
(1..5)           #=> [1, 2, 3, 4, 5]
('a'..'e')       #=> ["a", "b", "c", "d", "e"]

#(...) operator
(-1...-5)         #=> []
(-5...-1)         #=> [-5, -4, -3, -2]
(1...5)           #=> [1, 2, 3, 4]
('a'...'e')       #=> ["a", "b", "c", "d"]

#new operator - Syntax: new(begin, end, exclude_end = false)
Range.new(-1,-5)    #=> []
Range.new(-5,-1)    #=> [-5, -4, -3, -2, -1]
Range.new(1,5)      #=> [1, 2, 3, 4, 5]
Range.new('a','e')  #=> ["a", "b", "c", "d", "e"]

When used as an iterator, ranges return each value in the sequence. Consider the example below where to_a method is used to convert ranges into array.

range1 = (1..5).to_a
range2 = ("abc".."abg").to_a

range3 = (100...105).to_a

range4 = Range.new("A", "E").to_a

#displaying the result
puts "#{range1}" 
puts "#{range2}" 
puts "#{range3}" 
puts "#{range4}" 

The output of the above code will be:

[1, 2, 3, 4, 5]
["abc", "abd", "abe", "abf", "abg"]
[100, 101, 102, 103, 104]
["A", "B", "C", "D", "E"]

Ranges implement methods that let a user to iterate over them and test their contents in a number of ways. Consider the example below.

MyRange = 1..8

#checking the content
retval = MyRange.include?(5)
puts "MyRange contains 5?: #{retval}"

#getting the minimum value
retval = MyRange.min
puts "MyRange minimum value: #{retval}"

#getting the maximum value
retval = MyRange.max
puts "MyRange maximum value: #{retval}"

#slicing the ranges
retval = MyRange.select {|i| i < 5 }
puts "MyRange selected: #{retval}"
retval = MyRange.reject {|i| i < 5 }
puts "MyRange rejected: #{retval}"

#iterating over the range
puts "MyRange contains:"
MyRange.each do |i|
   puts i
end

The output of the above code will be:

MyRange contains 5?: true
MyRange minimum value: 1
MyRange maximum value: 8
MyRange selected: [1, 2, 3, 4]
MyRange rejected: [5, 6, 7, 8]
MyRange contains:
1
2
3
4
5
6
7
8

Ranges as Conditions

Ranges can also be used to define conditional expressions. Consider the example below where conditional expressions are defined using ranges in a case statement.

marks = 55

grade = case marks
   when 0..35 then "Fail"
   when 36..50 then "Grade D"
   when 51..65 then "Grade C"
   when 66..80 then "Grade B"
   when 81..100 then "Grade A"
   else "Invalid Score"
end

puts grade

The output of the above code will be:

Grade C

Ranges as Intervals

Ranges can also be used to defined intervals to check that the given value falls within the interval or not. It is represented by equality operator(===).

i = 55

if((1..50) === i)
  puts "#{i} lies between 1 and 50."
elsif((51..100) === i)
  puts "#{i} lies between 51 and 100."
else
  puts "#{i} do not lie between 1 and 100."
end

The output of the above code will be:

55 lies between 51 and 100.