2009-05-15 13 views
112

J'ai besoin d'écrire une boucle qui fait quelque chose comme:Déterminer si une variable est dans la plage?

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, sont descendus les mauvais chemins en termes de syntaxe.

Répondre

77

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

if (1..10) === i 
+1

a la belle avantage de travailler aussi avec 'être I' quelque chose d'autre qu'un nombre (comme 'nil') –

+3

Ne semblerait pas être une solution très efficace si la portée avait été significativement grand. – rthbound

+4

Pour le futur lecteur, l'autre méthode 'if i === (1..10)' ne fonctionnera pas – Anwar

34

si vous voulez quand même 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 
+5

Je pense que cela aurait dû être la réponse marquée. – Geo

65

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

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

de toutes les réponses, c'est aussi probablement le plus performant lorsque vous avez plusieurs gammes. – xentek

0

Une réponse plus dynamique, qui c un être construit en 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 

Ainsi, dans ce cas, les « plages » sont vraiment juste clôturé avec nils afin de capturer les conditions aux limites.

273
 
if i.between?(1, 10) 
    do thing 1 
elsif i.between?(11,20) 
    do thing 2 
... 
+3

Cela fonctionne également pour les objets 'Date' et' DateTime' alors que '===' ne fonctionne pas. – Aditya

+0

'i.between? (1..10)' ne fonctionnera pas (si c'est '..') Je suppose qu'il doit y avoir une raison pour cela –

+0

** entre? ** aurait besoin de deux paramètres, il ne permettrait pas gamme. –

-2

For Strings:

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

# => true

6

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

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

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

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

vrai

2

Vous pouvez 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 que include?

+0

Ceci est en réalité beaucoup plus rapide –

Questions connexes