Определение, находится ли переменная в пределах диапазона?

134

Мне нужно написать цикл, который делает что-то вроде:

if i (1..10)
  do thing 1
elsif i (11..20)
  do thing 2
elsif i (21..30)
  do thing 3
etc...

Но до сих пор пошли по неверному пути с точки зрения синтаксиса.

кстати
источник

Ответы:

306
если между? (1, 10)
  сделать вещь 1 
elsif i.between? (11,20)
  сделать вещь 2 
...
rogerdpack
источник
3
Это также работает Dateи DateTimeобъекты , а ===не делает.
Адитья
i.between?(1..10)не будет работать (если это так ..), я полагаю, должна быть причина для этого
неполярность
между? потребовалось бы два параметра, это не позволило бы диапазон.
Маниш Нагдевани
5
это включительно или эксклюзивно?
Andrewcockerham
1
@andrewcockerham включительно. 3.between?(1, 3) => true
Тайлер Джеймс Янг
84

Используйте ===оператор (или его синоним include?)

if (1..10) === i
Бакин
источник
1
Имеет приятное преимущество также работать с iчем-то, кроме числа (например nil)
Кристоффер Кланг
4
Не показалось бы очень эффективным решением, если бы диапазон был значительно большим.
2011 г.
6
Для будущего читателя альтернативный путь if i === (1..10)не сработает
Анвар
@ rthbound, почему? (1..10000000000000000) не массив (1..10000000000000000) === 5000000000000000просто делает «промежуточный» тест под капотом
John La Rooy
1
@ Анвар, не могли бы вы объяснить, почему это не работает по-другому?
Говинд Рай
70

Как сказал @Baldu, используйте оператор === или используйте case /, когда внутренне используется ===:

case i
when 1..10
  # do thing 1
when 11..20
  # do thing 2
when 21..30
  # do thing 3
etc...
Винсент Роберт
источник
из всех ответов, это также, вероятно, самый эффективный, когда у вас есть несколько диапазонов.
xentek
40

если вы все еще хотите использовать диапазоны ...

def foo(x)
 if (1..10).include?(x)
   puts "1 to 10"
 elsif (11..20).include?(x)
   puts "11 to 20"
 end
end
Тим Хулихан
источник
8

Обычно вы можете получить намного лучшую производительность с чем-то вроде:

if i >= 21
  # do thing 3
elsif i >= 11
  # do thing 2
elsif i >= 1
  # do thing 1
Брэд Верт
источник
8

Вы могли бы использовать
if (1..10).cover? i then thing_1 elsif (11..20).cover? i then thing_2

и в соответствии с этим тестом в Fast Ruby быстрее, чемinclude?

Хуан Фелипе Родригес
источник
Это на самом деле намного быстрее
Джо Половина
5

Не прямой ответ на вопрос, но если вы хотите противоположность «внутри»:

(2..5).exclude?(7)

правда

Незнакомец
источник
Обратите внимание, что exclude?это дополнение к Rails .
Ян Климо
1

Более динамичный ответ, который можно встроить в Ruby:

def select_f_from(collection, point) 
  collection.each do |cutoff, f|
    if point <= cutoff
      return f
    end
  end
  return nil
end

def foo(x)
  collection = [ [ 0, nil ],
                 [ 10, lambda { puts "doing thing 1"} ],
                 [ 20, lambda { puts "doing thing 2"} ],
                 [ 30, lambda { puts "doing thing 3"} ],
                 [ 40, nil ] ]

  f = select_f_from(collection, x)
  f.call if f
end

Таким образом, в этом случае, «диапазоны» на самом деле просто ограничены нулями, чтобы поймать граничные условия.

M104
источник
-2

Для строк:

(["GRACE", "WEEKLY", "DAILY5"]).include?("GRACE")

# => Верно

Видур Пендж
источник