Пара вещей, которые нужно отметить в вашем коде:
- вы, кажется, игнорируете месяц и день рождения пользователя
Вы конвертируете в и из строк без необходимости:
50.years.ago.strftime("%Y").to_i
можно записать как
50.years.ago.year
жестко закодированные значения по всему коду
Я бы начал переписывать с поиска подходящего метода для расчета точного возраста. Этот вроде бы в порядке:
require 'date'
def age(dob)
now = Time.now.utc.to_date
now.year - dob.year - ((now.month > dob.month || (now.month == dob.month && now.day >= dob.day)) ? 0 : 1)
end
Затем я бы извлек таблицу возраста в отдельную структуру, чтобы можно было легко изменить ее при необходимости и визуально собрать вместе:
INF = 1/0.0 # convenient infinity
age_groups = {
(0..18) => 'Under 18',
(19..24) => '19-24',
(25..35) => '25-35',
(36..50) => '36-50',
(51..69) => '51-69',
(70..INF) => '70+'
}
Далее вы можете взять в качестве входных данных массив дат рождения пользователей:
users_dobs = [Date.new(1978,4,16), Date.new(2001,6,13), Date.new(1980,10,22)]
И начинаем искать подходящий метод для группировки их на основе вашей карты, скажем, используя inject
:
p users_dobs.each_with_object({}) {|dob, result|
age_group = age_groups.keys.find{|ag| ag === age(dob)}
result[age_group] ||= 0
result[age_group] += 1
}
#=>{25..35=>2, 0..18=>1}
или, возможно, используя group_by
p users_dobs.group_by{|dob|
age_groups.keys.find{|ag| ag === age(dob)}
}.map{|k,v| [age_groups[k], v.count]}
#=>[["25-35", 2], ["Under 18", 1]]
и т.д.