Feststellen, ob eine Variable innerhalb des Bereichs liegt?

134

Ich muss eine Schleife schreiben, die ungefähr so ​​funktioniert:

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

Aber bisher sind wir in Bezug auf die Syntax die falschen Wege gegangen.

Übrigens
quelle

Antworten:

306
wenn zwischen? (1, 10)
  mach was 1 
sonst zwischen? (11,20)
  mach was 2 
...
Rogerdpack
quelle
3
Dies funktioniert auch für Dateund DateTimeObjekte, während ===dies nicht der Fall ist.
Aditya
i.between?(1..10)wird nicht funktionieren (wenn es so ist ..) Ich nehme an, es muss einen Grund dafür geben
Unpolarität
zwischen? würde zwei Parameter benötigen, die keinen Bereich zulassen würden.
Manish Nagdewani
5
ist es inklusive oder exklusiv?
Andrewcockerham
1
@ andrewcockerham Inklusive. 3.between?(1, 3) => true
Tyler James Young
84

Verwenden Sie den ===Operator (oder sein Synonym include?)

if (1..10) === i
Baldu
quelle
1
Hat den schönen Vorteil, auch damit zu arbeiten i, etwas anderes als eine Zahl (wie nil) zu sein
Christoffer Klang
4
Wäre keine sehr effiziente Lösung, wenn die Reichweite erheblich gewesen wäre.
Rthbound
6
Für zukünftige Leser wird der alternative Weg if i === (1..10)nicht funktionieren
Anwar
@rthbound, warum? (1..10000000000000000) ist kein Array. (1..10000000000000000) === 5000000000000000macht gerade einen "Zwischen" -Test unter der Haube
John La Rooy
1
@Anwar kannst du erklären warum es nicht anders funktioniert?
Govind Rai
70

Verwenden Sie, wie @Baldu sagte, den Operator === oder den Anwendungsfall / when, der intern === verwendet:

case i
when 1..10
  # do thing 1
when 11..20
  # do thing 2
when 21..30
  # do thing 3
etc...
Vincent Robert
quelle
Von allen Antworten ist dies wahrscheinlich auch die leistungsstärkste, wenn Sie mehrere Bereiche haben.
Xentek
40

wenn Sie noch Bereiche verwenden wollten ...

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

Normalerweise erzielen Sie eine viel bessere Leistung mit:

if i >= 21
  # do thing 3
elsif i >= 11
  # do thing 2
elsif i >= 1
  # do thing 1
Brad Werth
quelle
8

Du könntest benutzen
if (1..10).cover? i then thing_1 elsif (11..20).cover? i then thing_2

und nach diesem Benchmark in Fast Ruby ist schneller alsinclude?

Juan Felipe Rodriguez
quelle
Dies ist tatsächlich viel schneller
Joe Half Face
5

Keine direkte Antwort auf die Frage, aber wenn Sie das Gegenteil von "innerhalb" wollen:

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

wahr

Fremder
quelle
Beachten Sie, dass dies exclude?ein Rails-Zusatz ist .
Jan Klimo
1

Eine dynamischere Antwort, die in Ruby erstellt werden kann:

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

In diesem Fall sind die "Bereiche" also wirklich nur mit Nullen eingezäunt, um die Randbedingungen zu erfassen.

m104
quelle
-2

Für Streicher:

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

# => wahr

vidur punj
quelle