Есть ли элегантный способ исключить первое значение диапазона? - PullRequest
12 голосов
/ 29 июля 2010

Допустим, у меня есть диапазон от 0 до 10:

range = 0...10

Три точки означают, что последнее значение (10) исключено:

range.include? 10
=> false

Теперь естьпохожий и элегантный способ исключения значения first ?
Для приведенного выше примера это будет означать включение всех значений, которые больше (>, не >=) чем 0 и меньше чем 10.

Ответы [ 3 ]

5 голосов
/ 30 июля 2010

У меня есть два предложения для вас, они не очень идеальны, но это лучшее, что я могу придумать.

Сначала вы можете определить новый метод в классе 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, я просто выбрал его, так как он соответствует * 1013 Range* method.

Edit: У меня есть еще один для вас, просто потому, что я нахожу эту проблему настолько интересной.: P Это будет работать только в самой последней версии Ruby 1.9, но позволит использовать следующий синтаксис:

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

Он использует ту же идею, что и мое второе предложение, но сохраняет маркер исключения вчисло вместо диапазона.Для этого мне нужно использовать SimpleDelegator в Ruby 1.9 (сами по себе числа не могут иметь переменных экземпляра или чего-либо еще), поэтому он не будет работать в более ранних версиях 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
3 голосов
/ 29 июля 2010

Нет.

((0+1)..10)
0 голосов
/ 30 июля 2010

Возможно, вы могли бы создать свой собственный тип диапазона.

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

  # insert more code here

end
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...