Reverse method `...` Ruby

Is there a standard method in ruby ​​similar to (1...4).to_a

is [1,2,3,4]

, other than the reverse ie (4...1).to_a

will [4,3,2,1]

?

I understand that it is easy to define through (1...4).to_a.reverse

, but it seems strange to me that it has not yet been and 1) Am I missing something? 2) if not, is there a functional / practical reason why this has not been done yet?

+3


source to share


3 answers


The easiest way is to do this:

4.downto(1).to_a #=> [4, 3, 2, 1]

      

Alternatively, you can use step

:



4.step(1,-1).to_a #=> [4, 3, 2, 1]

      

Finally, a rather obscure solution for fun:

(-4..-1).map(&:abs) #=> [4, 3, 2, 1]

      

+9


source


(1...4)

is the range. Ranges in ruby ​​are not like arrays; one if their advantages are that you can create a range like

(1..1e9)

      

without taking up all the memory of the device. Alternatively, you can create this range:

r = (1.0...4.0)

      

Which means "the set of all floating point numbers from 1.0 to 4.0, including 1.0, but not 4.0"

In other words:

irb(main):013:0> r.include? 3.9999
=> true
irb(main):014:0> r.include? 3.99999999999
=> true
irb(main):015:0> r.include? 4.0
=> false

      



you can turn an integer range into an array:

irb(main):022:0> (1..4).to_a
=> [1, 2, 3, 4]

      

but not a floating point range:

irb(main):023:0> (1.0...4.0).to_a
TypeError: can't iterate from Float
        from (irb):23:in `each'
        from (irb):23:in `to_a'
        from (irb):23
        from /home/mslade/rubygems1.9/bin/irb:12:in `<main>'

      

Because there is no natural way to iterate over floating point numbers. Instead, you use #step

:

irb(main):015:0> (1..4).step(0.5).to_a
=> [1.0, 1.5, 2.0, 2.5, 3.0, 3.5, 4.0]
irb(main):016:0> (1...4).step(0.5).to_a
=> [1.0, 1.5, 2.0, 2.5, 3.0, 3.5]

      

If you need to iterate backwards through a large integer range, use Integer#downto

.

+8


source


You can fix Range # to_a to automatically work the opposite:

class Range

  alias :to_a_original :to_a

  def reverse
    Range.new(last, first)
  end

  def to_a
    (first < last) ? to_a_original : reverse.to_a_original.reverse
  end

end

      

Result:

(4..1).to_a
=> [4, 3, 2, 1]

      

This approach is called "reopening" the aka "monkey-patching" class. Some developers like this approach because it adds useful features, some don't like it because it tinkers with the Ruby core.)

+1


source







All Articles