如何在Ruby中构建范围?

时间:2016-10-12 00:09:12

标签: ruby

是否可以在ruby中使用解构来提取结束并从范围开始?

module PriceHelper
  def price_range_human( range )
    "$%s to $%s" % [range.begin, range.end].map(:number_to_currency)
  end
end

我知道我可以使用数组强制作为一个非常糟糕的黑客:

first, *center, last = *rng
"$%s to $%s" % [first, last].map(:number_to_currency)

但有没有一种语法方法可以在不实际手动创建数组的情况下获取beginend

min, max = (1..10)

本来很棒。

4 个答案:

答案 0 :(得分:4)

开始和结束?我会用:

foo = 1..2
foo.min # => 1
foo.max # => 2

尝试对范围使用解构是一个坏主意。想象一下可以生成然后丢弃的数组大小,浪费CPU时间和内存。如果您的范围以Float::INFINITY结尾,那么它实际上是DOS自己代码的好方法。

  

endmax不同:在1 ... 10中,end为10,但max为9

那是因为start_val ... end_val相当于start_val .. (end_val - 1)

start_value = 1
end_value = 2

foo = start_value...end_value
foo.end # => 2
foo.max # => 1

foo = start_value..(end_value - 1)
foo.end # => 1
foo.max # => 1

max反映了Ruby在迭代范围或测试包含在范围内时实际使用的值的实际情况。

在我看来,end应该反映在范围内将考虑的实际最大值,而不是在范围定义结束时使用的值,但我怀疑否则会改变它' d影响现有代码。

...更容易混淆并导致维护问题增加,因此不建议使用它。

答案 1 :(得分:3)

您可以使用minmax来构建简单范围:

min, max = (1..10).minmax
min # => 1
max # => 10

答案 2 :(得分:2)

不,在被Cary Swoveland,周刊世界新闻或其他小报证明不正确之前,我会继续相信没有任何证据表明答案是"没有" ;但它很容易制作。

module RangeWithBounds
  refine Range do
    def bounds
      [self.begin, self.end]
    end
  end
end

module Test
  using RangeWithBounds
  r = (1..10)
  b, e = *r.bounds
  puts "#{b}..#{e}"
end

然后,我首先要写"#{r.begin.number_to_currency}..#{r.end.number_to_currency}"

答案 3 :(得分:0)

Amadan的答案很好。你只需要在使用它时删除splat(*),因为它不需要

例如

> "%s to %s" % (1..3).bounds.map{|x| number_to_currency(x)}
=> "$1.00 to $3.00"