Ustalanie, czy zmienna mieści się w zakresie?


134

Muszę napisać pętlę, która robi coś takiego:

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

Ale do tej pory poszli złymi ścieżkami pod względem składni.

Odpowiedzi:


306
if i. between? (1, 10)
  zrób rzecz 1 
elsif i.between? (11,20)
  zrób coś 2 
...

3
Działa to również w przypadku obiektów Datei, DateTimepodczas gdy ===nie.
Aditya

i.between?(1..10)nie zadziała (jeśli jest ..) Przypuszczam, że musi być ku temu powód
niepolarność

pomiędzy? wymagałby dwóch parametrów, nie pozwoliłby na zakres.
Manish Nagdewani

5
czy jest inkluzywny czy ekskluzywny?
andrewcockerham

1
@andrewcockerham Inclusive. 3.between?(1, 3) => true
Tyler James Young

84

Użyj ===operatora (lub jego synonimu include?)

if (1..10) === i

1
Ma tę zaletę, że pracuje się z ikimś innym niż liczba (na przykład nil)
Christoffer Klang,

4
Nie wydawałoby się bardzo wydajnym rozwiązaniem, gdyby zasięg był znacznie duży.
rthbound

6
Dla przyszłego czytelnika alternatywny sposób if i === (1..10)nie zadziała
Anwar

@rthbound, dlaczego? (1..10000000000000000) nie jest tablicą. (1..10000000000000000) === 5000000000000000robi tylko test „pomiędzy” pod maską
John La Rooy,

1
@Anwar czy możesz wyjaśnić, dlaczego to nie działa w drugą stronę?
Govind Rai

70

Jak powiedział @Baldu, użyj operatora === lub przypadku użycia / kiedy wewnętrznie używa ===:

case i
when 1..10
  # do thing 1
when 11..20
  # do thing 2
when 21..30
  # do thing 3
etc...

spośród wszystkich odpowiedzi jest to prawdopodobnie najbardziej wydajne rozwiązanie, gdy masz wiele zakresów.
xentek

40

jeśli nadal chcesz używać zakresów ...

def foo(x)
 if (1..10).include?(x)
   puts "1 to 10"
 elsif (11..20).include?(x)
   puts "11 to 20"
 end
end

8

Zwykle można uzyskać znacznie lepszą wydajność, stosując coś takiego:

if i >= 21
  # do thing 3
elsif i >= 11
  # do thing 2
elsif i >= 1
  # do thing 1



1

Bardziej dynamiczna odpowiedź, którą można zbudować w Rubim:

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

Tak więc w tym przypadku „zakresy” są tak naprawdę ogrodzone zerami, aby uchwycić warunki brzegowe.


Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.