询问Ruby数组的哈希值

use*_*972 3 ruby ruby-on-rails

我需要在Ruby中按年龄分组人员.我有他们的出生日期,以及一种多年回归年龄的方法.所以像这样的解决方案有效.

case
when (0..15).cover?(age_years)
  'child'
when (16..24).cover?(age_years)
  '16 to 24'
when (25..34).cover?(age_years)
  '25 to 34'
when (35..44).cover?(age_years)
  '35 to 44'
when (45..54).cover?(age_years)
  '45 to 54'
when (55..64).cover?(age_years)
  '55 to 64'
when age_years > 64
  'really old'
else
  'unknown'
end
Run Code Online (Sandbox Code Playgroud)

但是,我正在努力学习Ruby,并且正在寻找更优雅的解决方案.我想把age_ranges放到像这样的哈希数组中......

age_ranges = [{ name: 'child', min_age: 0, max_age: 15 },
              { name: '16 to 24', min_age: 16, max_age: 24 }]
Run Code Online (Sandbox Code Playgroud)

但我不知道如何查询这些数据以返回正确的名称,其中age_years在适当的范围内,甚至是这样的范围

age_ranges = [{ name: 'child', age_range: '0..15' },
              { name: '16 to 24', age_range: '16..24' }]
Run Code Online (Sandbox Code Playgroud)

看起来更整洁,但我不知道我是否写了胡言乱语,因为我不知道如何在年龄匹配时提取名称.

有人能指出我正确的方向吗?

And*_*eko 5

既然你有一个年龄名称和范围的地图(注意我使用了范围,而不是字符串作为值age_range),你想要搜索这样age_ranges的哈希数组,其值age_range包括年龄:

def age_ranges
  [
    { name: 'child',    age_range: 0..15 },
    { name: '16 to 24', age_range: 16..24 }
  ]
end

def find_age(age)
  age_ranges.find { |hash| hash[:age_range].include?(age) }[:name]
end

find_age(12)
#=> "child"
find_age(17)
#=> "16 to 24"
Run Code Online (Sandbox Code Playgroud)

注意,[:name]如果find返回将失败nil(意思是,找不到匹配项).

要克服它,要么添加一个无限范围作为数组中的最后一个(我更喜欢这个,因为它更简单):

def age_ranges
  [
    { name: 'child',    age_range: 0..15 },
    { name: '16 to 24', age_range: 16..24 },
    { name: 'unknown',  age_range: 25..Float::INFINITY }
  ]
end
Run Code Online (Sandbox Code Playgroud)

或者在find_age方法中获取年龄时处理它:

def find_age(age)
  age_ranges.each_with_object('unknown') { |hash, _| break hash[:name] if hash[:age_range].include?(age) }
end
Run Code Online (Sandbox Code Playgroud)

此外,请确保处理传递给方法的负数(因为age_ranges不包括负数):

def find_age(age)
  return 'Age can not be less than 0' if age.negative?
  age_ranges.find { |hash| hash[:age_range].include?(age) }[:name]
end
Run Code Online (Sandbox Code Playgroud)

PS在所有这些"注意/确定"之后我想说@ mudasobwa的答案是最简单的方法:)


Ale*_*kin 5

Range#===因为它应该被使用,直接使用三等号:

case age_years
when 0..15 then 'child'
when 16..24 then '16 to 24'
when 25..34 then '25 to 34'
when 35..44 then '35 to 44'
when 45..54 then '45 to 54'
when 55..64 then '55 to 64'
when 64..Float::INFINITY then 'really old' # or when 64.method(:<).to_proc
else 'unknown'
end
Run Code Online (Sandbox Code Playgroud)

要使case接受浮点数,应使用三点范围:

case age_years
when 0...16 then 'child'
when 16...25 then '16 to 24'
when 25...35 then '25 to 34'
when 35...45 then '35 to 44'
when 45...55 then '45 to 54'
when 55...64 then '55 to 64'
when 64..Float::INFINITY then 'really old' # or when 64.method(:<).to_proc
else 'unknown'
end
Run Code Online (Sandbox Code Playgroud)