Bill Parker
Bill Parker

Reputation: 135

in Ruby, how do I push elements to the end of a range?

Is there any way to push elements onto the end of a range without converting it into an array then back to a range?

r = 1..10
=> 1..10

r << 11
NoMethodError: undefined method `<<' for 1..10:Range

r.push 11
NoMethodError: undefined method `push' for 1..10:Range

Upvotes: 3

Views: 193

Answers (3)

Thomas Klemm
Thomas Klemm

Reputation: 10856

You cannot extend a range by pushing the next elements to it. You can however extend the Range class to support for modifying ranges in any way you need.

class Range
  def end_at(x)
    Range.new(self.begin, x)
  end

  def start_at(x)
    Range.new(x, self.end)
  end
end

# Initial Range
range = 1..10

# New end
p range.end_at(100)
# => 1..100

# New start
p range.start_at(5)
# => 1..5

Upvotes: 0

Lee Jarvis
Lee Jarvis

Reputation: 16241

A range is simply an interval. A start and an end. You don't just push values on the end of a Range. You either convert the Range to an array

items = range.to_a
items << 11

Or you create a new range..

Range.new(range.begin, 11)

EDIT: The reason we use #begin on the range and not #first is because first and last build a new array from the Range, we don't want that.. we just want the begin or end values instead.

Upvotes: 5

d11wtq
d11wtq

Reputation: 35298

You can't. A Range is not an Array, or a Set, or a collection at all really. It's just a representation of an upper and lower bound. You can iterate one because it's possible to step between the upper and lower bounds. You can also turn one into an Array (using Range#to_a), which just iterates and collects the values into an Array.

If you want to expand or shrink the Range, create a new Range based on its #begin and #end.

new_range = Range(old_range.begin, old_range.end + 1)

Upvotes: 3

Related Questions