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

Dan*_*sch 12 ruby range

假设我的范围是0到10:

range = 0...10
Run Code Online (Sandbox Code Playgroud)

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

range.include? 10
=> false
Run Code Online (Sandbox Code Playgroud)

现在,有没有类似和优雅的方法来排除第一个值?
对于上面的例子,这将意味着以包括所有的值更大(>, >=)大于0且于10.

Adr*_*ian 5

不。

((0+1)..10)
Run Code Online (Sandbox Code Playgroud)

  • 从 Ruby 2.2 开始,你可以使用 `(0.0).next_float..10.0` (14认同)
  • 唯一的问题是,0 到 1 之间的值不会被包含在内。是的,您可以说“0.00000001..10”(或类似的内容,具体取决于您需要多少位小数)。但在我看来,当我想说的是:“0 < range < 10”时,这相当难看。 (3认同)
  • @Envek - 你应该将其作为一个单独的答案。非常适合我的用例! (2认同)

Jer*_*ten 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
Run Code Online (Sandbox Code Playgroud)

我不知道,我只是使用"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
Run Code Online (Sandbox Code Playgroud)

同样,你可能想要一个更好(更优雅?)的方法名称exclude_begin,我只是选择它,因为它与Range的exclude_end?方法一致.

编辑:我有另一个给你,因为我发现这个问题很有趣.:P这只适用于最新版本的Ruby 1.9,但允许使用以下语法:

(0.exclude..10).include? 0       #=> false
(0.exclude..10).include? 0.00001 #=> true
Run Code Online (Sandbox Code Playgroud)

它使用与我的第二个建议相同的想法,但将"排除标记"存储在数字而不是范围中.我必须使用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
Run Code Online (Sandbox Code Playgroud)