Déterminer si une variable est dans la plage?

134

J'ai besoin d'écrire une boucle qui fait quelque chose comme:

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

Mais jusqu'à présent, ils ont emprunté les mauvais chemins en termes de syntaxe.

btw
la source

Réponses:

306
si i.entre? (1, 10)
  faire la chose 1 
elsif i.entre? (11,20)
  faire la chose 2 
...
rogerdpack
la source
3
Cela fonctionne également pour Dateet les DateTimeobjets, mais ===pas.
Aditya
i.between?(1..10)ne fonctionnera pas (si c'est le cas ..) Je suppose qu'il doit y avoir une raison à cela
nonopolarité
entre? aurait besoin de deux paramètres, il ne permettrait pas la plage.
Manish Nagdewani
5
est-ce inclusif ou exclusif?
andrewcockerham
1
@andrewcockerham inclus. 3.between?(1, 3) => true
Tyler James Young
84

Utilisez l' ===opérateur (ou son synonyme include?)

if (1..10) === i
Baldu
la source
1
A l'avantage de travailler avec iautre chose qu'un nombre (comme nil)
Christoffer Klang
4
Cela ne semblerait pas être une solution très efficace si la portée avait été considérablement large.
rthbound
6
Pour le futur lecteur, la méthode alternative if i === (1..10)ne fonctionnera pas
Anwar
@rthbound, pourquoi? (1..10000000000000000) n'est pas un tableau. (1..10000000000000000) === 5000000000000000fait juste un test "entre" sous le capot
John La Rooy
1
@Anwar pourriez-vous expliquer pourquoi cela ne fonctionne pas dans l'autre sens?
Govind Rai
70

Comme @Baldu l'a dit, utilisez l'opérateur === ou utilisez le cas / quand qui utilise en interne ===:

case i
when 1..10
  # do thing 1
when 11..20
  # do thing 2
when 21..30
  # do thing 3
etc...
Vincent Robert
la source
de toutes les réponses, c'est probablement aussi la plus performante lorsque vous avez plusieurs plages.
xentek
40

si vous vouliez toujours utiliser des plages ...

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
la source
8

Vous pouvez généralement obtenir de bien meilleures performances avec quelque chose comme:

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

Vous pourriez utiliser
if (1..10).cover? i then thing_1 elsif (11..20).cover? i then thing_2

et selon cette référence dans Fast Ruby est plus rapide queinclude?

Juan Felipe Rodriguez
la source
C'est en fait beaucoup plus rapide
Joe Half Face
5

Pas une réponse directe à la question, mais si vous voulez le contraire de "dedans":

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

vrai

Fellow étranger
la source
Notez qu'il exclude?s'agit d'un ajout de Rails .
Jan Klimo
1

Une réponse plus dynamique, qui peut être intégrée dans 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

Donc, dans ce cas, les «plages» sont en réalité simplement délimitées par des nils afin de capturer les conditions aux limites.

m104
la source
-2

Pour les cordes:

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

# => vrai

vidur punj
la source