Menentukan apakah suatu variabel berada dalam jangkauan?

136

Saya perlu menulis loop yang melakukan sesuatu seperti:

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

Namun sejauh ini telah menempuh jalan yang salah dalam hal sintaksis.

btw
sumber

Jawaban:

310
jika i.between? (1, 10)
  lakukan hal 1 
elsif i.between? (11,20)
  lakukan hal 2 
...
rogerdpack
sumber
3
Ini juga bekerja untuk objek Datedan DateTimesementara ===tidak.
Aditya
i.between?(1..10)tidak akan berfungsi (jika ya ..) Saya kira pasti ada alasan untuk itu
nonopolaritas
antara? akan membutuhkan dua parameter yang tidak memungkinkan jangkauan.
Manish Nagdewani
6
apakah itu inklusif atau eksklusif?
andrewcockerham
2
@andrianty 3.between?(1, 3) => true
Tyler James Young
86

Gunakan ===operator (atau sinonimnya include?)

if (1..10) === i
Baldu
sumber
1
Memiliki manfaat bagus juga bekerja dengan imenjadi sesuatu yang lain selain angka (seperti nil)
Christoffer Klang
4
Tidak akan tampak seperti solusi yang sangat efisien jika jangkauannya sangat besar.
rthbound
6
Untuk pembaca yang akan datang, cara alternatif if i === (1..10)tidak akan berhasil
Anwar
@rthbound, kenapa? (1..10000000000000000) bukanlah sebuah array. (1..10000000000000000) === 5000000000000000hanya melakukan tes "antara" di bawah tenda
John La Rooy
1
@Anwar Bisakah Anda menjelaskan mengapa itu tidak bekerja dengan cara lain?
Govind Rai
70

Seperti yang dikatakan @Baldu, gunakan operator === atau use case / saat yang secara internal menggunakan ===:

case i
when 1..10
  # do thing 1
when 11..20
  # do thing 2
when 21..30
  # do thing 3
etc...
Vincent Robert
sumber
dari semua jawaban, ini juga kemungkinan yang paling berkinerja jika Anda memiliki beberapa rentang.
xentek
40

jika Anda masih ingin menggunakan rentang ...

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

Anda biasanya bisa mendapatkan kinerja yang jauh lebih baik dengan sesuatu seperti:

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

Anda bisa menggunakan
if (1..10).cover? i then thing_1 elsif (11..20).cover? i then thing_2

dan menurut benchmark ini di Fast Ruby lebih cepat dariinclude?

Juan Felipe Rodriguez
sumber
Ini sebenarnya jauh lebih cepat
Joe Half Face
5

Bukan jawaban langsung untuk pertanyaan tersebut, tetapi jika Anda ingin kebalikan dari "dalam":

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

benar

Fellow Stranger
sumber
Perhatikan itu exclude?adalah tambahan Rails .
Jan Klimo
1

Jawaban yang lebih dinamis, yang dapat dibangun di 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

Jadi, dalam kasus ini, "range" sebenarnya hanya dipagari dengan nil untuk menangkap kondisi batas.

m104
sumber
-2

Untuk String:

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

# => benar

vidur punj
sumber