¿Determinar si una variable está dentro del rango?

134

Necesito escribir un bucle que haga algo como:

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

Pero hasta ahora hemos recorrido caminos equivocados en términos de sintaxis.

por cierto
fuente

Respuestas:

306
si i.entre? (1, 10)
  hacer cosa 1 
elsif i.entre? (11,20)
  hacer cosa 2 
...
rogerdpack
fuente
3
Esto también funciona para Datey DateTimeobjetos mientras ===que no.
Aditya
i.between?(1..10)no funcionará (si es así ..) supongo que debe haber una razón para ello
polaridad
¿Entre? necesitaría dos parámetros, no permitiría el rango.
Manish Nagdewani
55
¿Es inclusivo o exclusivo?
andrewcockerham
1
@andrewcockerham Inclusive. 3.between?(1, 3) => true
Tyler James Young
84

Use el ===operador (o su sinónimo include?)

if (1..10) === i
Baldu
fuente
1
Tiene la ventaja de trabajar también con iser algo más que un número (como nil)
Christoffer Klang
44
No parecería una solución muy eficiente si el rango hubiera sido significativamente grande.
2013
66
Para el futuro lector, la forma alternativa if i === (1..10)no funcionará
Anwar
@rthbound, ¿por qué? (1..10000000000000000) No es una matriz. (1..10000000000000000) === 5000000000000000solo está haciendo una prueba "entre" bajo el capó
John La Rooy
1
@Anwar, ¿podrías explicar por qué no funciona a la inversa?
Govind Rai
70

Como dijo @Baldu, use el operador === o use case / when que internamente usa ===:

case i
when 1..10
  # do thing 1
when 11..20
  # do thing 2
when 21..30
  # do thing 3
etc...
Vincent Robert
fuente
De todas las respuestas, este también es probablemente el más eficaz cuando tiene múltiples rangos.
xentek
40

si aún quisieras usar rangos ...

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
fuente
8

Por lo general, puede obtener un rendimiento mucho mejor con algo como:

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

Podrías usar
if (1..10).cover? i then thing_1 elsif (11..20).cover? i then thing_2

y de acuerdo con este punto de referencia en Fast Ruby es más rápido queinclude?

Juan felipe rodriguez
fuente
En realidad, esto es mucho más rápido
Joe Half Face
5

No es una respuesta directa a la pregunta, pero si desea lo contrario a "dentro":

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

cierto

Extraño compañero
fuente
Tenga en cuenta que exclude?es una adición de Rails .
Jan Klimo
1

Una respuesta más dinámica, que se puede construir 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

Entonces, en este caso, los "rangos" realmente están cercados con nulos para capturar las condiciones de contorno.

m104
fuente
-2

Para cuerdas:

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

# => verdadero

vidur punj
fuente