slh*_*hck 2 ruby arrays hash date
假设我有一个Date类似的Ruby数组:
2011-01-20
2011-01-23
2011-02-01
2011-02-15
2011-03-21
Run Code Online (Sandbox Code Playgroud)
什么是一种简单易用的Ruby方式创建一个Hash,按年和月分组Date元素,如:
{
2011 => {
1 => [2011-01-20, 2011-01-23],
2 => [2011-02-01, 2011-02-15],
3 => [2011-03-21],
}
}
Run Code Online (Sandbox Code Playgroud)
我可以通过迭代所有内容并提取数年,数月等来实现这一点,然后将它们组合起来.
Ruby为Arrays和Hashes提供了很多方法和块,必须有一个更简单的方法吗?
Mla*_*vić 17
require 'date'
dates = [
'2011-01-20',
'2011-01-23',
'2011-02-01',
'2011-02-15',
'2011-03-21'
].map{|sd| Date.parse(sd)}
Hash[
dates.group_by(&:year).map{|y, items|
[y, items.group_by{|d| d.strftime('%B')}]
}
]
#=> {2011=>{"January"=>[#<Date: 2011-01-20 (4911163/2,0,2299161)>, #<Date: 2011-01-23 (4911169/2,0,2299161)>], "February"=>[#<Date: 2011-02-01 (4911187/2,0,2299161)>, #<Date: 2011-02-15 (4911215/2,0,2299161)>], "March"=>[#<Date: 2011-03-21 (4911283/2,0,2299161)>]}}
Run Code Online (Sandbox Code Playgroud)
我注意到您已将月份名称更改为数字,因此您可能希望将d.strftime('%B')上面的名称替换为d.month其他内容.
这是一步一步的解释:
您基本上需要两级分组:第一级逐级,逐级逐级.Ruby有非常有用的方法group_by,它通过给定的表达式(块)对元素进行分组.所以:第一部分是对原始数组进行分组year:
hash_by_year = dates.group_by(&:year)
# => {2011=>[#<Date: 2011-01-20 (4911163/2,0,2299161)>, #<Date: 2011-01-23 (4911169/2,0,2299161)>, #<Date: 2011-02-01 (4911187/2,0,2299161)>, #<Date: 2011-02-15 (4911215/2,0,2299161)>, #<Date: 2011-03-21 (4911283/2,0,2299161)>]}
Run Code Online (Sandbox Code Playgroud)
这给了我们第一级:键是年,值是给定年份的日期数组.但是我们仍然需要对第二级进行分组:这就是为什么我们按年份哈希映射 - 将其值分组month.让我们开始忘记strftime并说我们分组d.month:
hash_by_year.map{|year, dates_in_year|
[year, dates_in_year.group_by(&:month)]
}
# => [[2011, {1=>[#<Date: 2011-01-20 (4911163/2,0,2299161)>, #<Date: 2011-01-23 (4911169/2,0,2299161)>], 2=>[#<Date: 2011-02-01 (4911187/2,0,2299161)>, #<Date: 2011-02-15 (4911215/2,0,2299161)>], 3=>[#<Date: 2011-03-21 (4911283/2,0,2299161)>]}]]
Run Code Online (Sandbox Code Playgroud)
这样我们就得到了第二级分组.现在我们有一个哈希,它的键是几个月,而不是一年中所有日期的数组,而是指定给定月份的日期数组.
我们唯一的问题是map返回一个数组而不是一个哈希.这就是为什么我们"围绕"整个表达式Hash[],在我们的案例对中使用对数组的哈希[year, hash_of_dates_by_month].
很抱歉,如果解释听起来令人困惑,我发现因为嵌套而难以解释功能表达而非命令.:(