是否有一种优雅的方法来排除范围的第一个值?

时间:2010-07-29 01:15:15

标签: ruby range

假设我的范围是0到10:

range = 0...10

三个点表示排除最后一个值(10):

range.include? 10
=> false

现在,是否有类似且优雅的方法来排除第一个值?
对于上面的示例,这意味着包含更大> >=)的所有值,而不是0和更小的值比10。

3 个答案:

答案 0 :(得分:5)

我有两条建议给你,它们不是很理想,但它们是我能想到的最好的。

首先,您可以在Range类上定义一个执行所描述内容的新方法。它看起来像这样:

class Range
  def have?(x)
    if x == self.begin
      false
    else
      include?(x)
    end
  end
end

p (0..10).have?(0)       #=> false
p (0..10).have?(0.00001) #=> true

我不知道,我只是使用“include”的同义词作为方法名称,也许你可以想到更好的东西。但这就是想法。

然后你可以做一些更精细的事情,并在Range类上定义一个方法,将一个范围标记为要排除其开始值的范围,然后更改Range的include?方法以检查那个标记。

class Range
  def exclude_begin
    @exclude_begin = true
    self
  end

  alias_method :original_include?, :include?
  def include?(x)
    return false if x == self.begin && instance_variable_defined?(:@exclude_begin)
    original_include?(x)
  end

  alias_method :===, :include?
  alias_method :member?, :include?
end

p (0..10).include?(0)                     #=> true
p (0..10).include?(0.00001)               #=> true
p (0..10).exclude_begin.include?(0)       #=> false
p (0..10).exclude_begin.include?(0.00001) #=> true

同样,您可能希望方法的名称比exclude_begin更好(更优雅?),我只是选择了它,因为它与Range的exclude_end?方法一致。

编辑:我还有另外一个,因为我觉得这个问题很有趣。 :P这只适用于最新版本的Ruby 1.9,但允许使用以下语法:

(0.exclude..10).include? 0       #=> false
(0.exclude..10).include? 0.00001 #=> true

它使用与我的第二个建议相同的想法,但将“排除标记”存储在数字而不是范围中。我必须使用Ruby 1.9的SimpleDelegator来实现这一点(数字本身不能有实例变量或任何东西),这就是为什么它不适用于早期版本的Ruby。

require "delegate"

class Numeric
  def exclude
    o = SimpleDelegator.new(self)
    def o.exclude_this?() true end
    o
  end
end

class Range
  alias_method :original_include?, :include?
  def include?(x)
    return false if x == self.begin &&
                    self.begin.respond_to?(:exclude_this?) &&
                    self.begin.exclude_this?
    original_include?(x)
  end

  alias_method :===, :include?
  alias_method :member?, :include?
end

答案 1 :(得分:3)

没有

((0+1)..10)

答案 2 :(得分:0)

也许您可以创建自己的范围类型。

class FancyRange
  def initialize(minimum, maximum, exclusive_minimum, exclusive_maximum)
    # insert code here
  end

  # insert more code here

end