反向`...`方法Ruby

时间:2012-04-06 06:35:11

标签: ruby

ruby​​中的标准方法与(1...4).to_a类似[1,2,3,4]除了反向,(4...1).to_a[4,3,2,1]吗?

我意识到这可以很容易地通过(1...4).to_a.reverse来定义,但它让我感到奇怪的是它已经不存在而且 1)我错过了什么? 2)如果没有,是否还有功能/实际原因?

3 个答案:

答案 0 :(得分:9)

最简单的可能就是:

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

或者,您可以使用step

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

最后一个相当模糊的解决方案:

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

答案 1 :(得分:8)

(1...4)是一个范围。红宝石中的范围与数组不同;一个,如果他们的优势是你可以创建像

这样的范围
(1..1e9)

不占用机器的所有内存。此外,您可以创建此范围:

r = (1.0...4.0)

这意味着“所有浮点数的集合从1.0到4.0,包括1.0但不是4.0”

换句话说:

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

您可以将整数范围转换为数组:

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

但不是浮点范围:

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>'

因为没有自然的方法来迭代浮点数。而是使用#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]

如果需要向后迭代一个大的整数范围,请使用Integer#downto

答案 2 :(得分:1)

您可以修改Range#to_a以自动使用反向操作:

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

结果:

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

这种方法被称为“重新开放”类a.k.a.“monkey-patching”。一些开发人员喜欢这种方法,因为它添加了有用的功能,有些人不喜欢它,因为它正在弄乱Ruby核心。)