I have some ranges defined:
very_low = <10
low = 11-20
medium = 21-30
high = 31-40
very_high = 41
What is the most succinct way in Ruby to find out which category any given number is in?
e.g know that 23 would be 'medium'
CodePudding user response:
I would do:
RANGES = {
very_low: (..10),
low: (11..20),
medium: (21..30),
high: (31..40),
very_high: (41..)
}
def range_for(number)
RANGES.find { |_, range| range.cover?(number) }.first
end
range_for(23)
#=> :medium
It uses Enumerable#find
with Range#cover?
to pick the matching range definition. The find
method returns an array including both, key and value. The chained first
call then picks the key from the array which will be the requested range identifier.
CodePudding user response:
you've changed your question, but you now have overlaps (40, and 40 ) ... I don't know if you're working with integers or decimals, but I'm assuming integers because you're not dealing with "10" or "10.5" ... how about this:
def which_range? num
ranges={
very_low: (..10),
low: (11..20),
medium: (21..30),
high: (31..40),
very_high: (41..)
}
ranges.each do |key,val|
return key if val.include?(num)
end
return false
end
example output:
2.7.2 :073 > which_range? 23
=> :medium
2.7.2 :074 > which_range? 7
=> :very_low
2.7.2 :075 > which_range? 25
=> :medium
2.7.2 :076 > which_range? 35
=> :high
2.7.2 :077 > which_range? 45
=> :very_high
2.7.2 :123 > which_range? 102
=> :very_high
2.7.2 :124 > which_range? -12
=> :very_low
CodePudding user response:
If I get your question correctly, then, perhaps, case statement is something you looking for
case some_number
when ..10 then 'very_low'
when 11..20 then 'low'
when 40.. then 'very_high'
...
end
# P.S.: for older versions without endless ranges:
case some_number
when -Float::INFINITY..10 then 'very_low'
when 11..20 then 'low'
when 40..Float::INFINITY then 'very_high'
...
end
CodePudding user response:
Assuming the ranges are consecutive, you could define the upper or lower bounds in an array in order from low to high (when using upper bounds) or from high to low (when using lower bounds). Then have an array with their respective name at the same index.
def range_name(number)
range_names = ['very_low', 'low', 'medium', 'high', 'very_high' ]
upper_bounds = [ 10 , 20 , 30 , 40 , Float::INFINITY] # inclusive
index = upper_bounds.find_index { |upper_bound| number <= upper_bound }
range_names[index]
end