按月和年将日期的 Ruby 数组分组为哈希
假设我有一个 Date
的 Ruby 数组,例如:
2011-01-20
2011-01-23
2011-02-01
2011-02-15
2011-03-21
创建按年和月对日期元素进行分组的哈希的简单且 Ruby 风格的方法是什么,例如:
{
2011 => {
1 => [2011-01-20, 2011-01-23],
2 => [2011-02-01, 2011-02-15],
3 => [2011-03-21],
}
}
我可以这样做通过迭代所有内容并提取年、月等,然后将它们组合起来。
Ruby 为数组和哈希提供了如此多的方法和块,一定有更简单的方法吗?
Let's say I had a Ruby Array of Date
s like:
2011-01-20
2011-01-23
2011-02-01
2011-02-15
2011-03-21
What would be an easy and Ruby-esque way of creating a Hash that groups the Date elements by year and then month, like:
{
2011 => {
1 => [2011-01-20, 2011-01-23],
2 => [2011-02-01, 2011-02-15],
3 => [2011-03-21],
}
}
I can do this by iterating over everything and extracting years, months and so on, then comining them.
Ruby offers so many methods and blocks for Arrays and Hashes, there must be an easier way?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
我注意到您已将月份名称更改为数字,因此您可能需要将上面的
d.strftime('%B')
替换为d.month
或其他内容。这是分步说明:
您本质上需要两级分组:第一级按年,第二级按月。 Ruby 有一个非常有用的方法
group_by
,它可以按给定的表达式(块)对元素进行分组。所以:第一部分是按年份对原始数组进行分组:这给了我们第一层:键是年份,值是给定年份的日期数组。但我们仍然需要对第二个级别进行分组:这就是我们按年映射哈希的原因 - 按
月
对其值进行分组。首先,让我们忘记strftime
并假设我们按d.month
进行分组:这样我们就得到了第二级分组。现在我们不再使用一年中所有日期的数组,而是使用以月份为键的哈希值以及给定月份的日期数组。
我们遇到的唯一问题是
map
返回一个数组而不是哈希值。这就是为什么我们用Hash[]
来“包围”整个表达式,这会从成对的数组中生成哈希,在我们的例子中是成对的[year, hash_of_dates_by_month]
。抱歉,如果解释听起来令人困惑,我发现由于嵌套,解释函数表达式比命令式更难。 :(
I noticed you have changed month names into numbers, so you may want to replace
d.strftime('%B')
above withd.month
or whatever else.Here's a step-by-step explanation:
You essentially want two-level grouping: first level by year, second by month. Ruby has very useful method
group_by
, which groups elements by given expression (a block). So: first part is grouping original array byyear
:That gives us first level: keys are years, values arrays of dates with given year. But we still need to group the second level: that's why we map by-year hash - to group its values by
month
. Let's for start forgetstrftime
and say that we're grouping byd.month
:That way we got our second level grouping. Instead of array of all dates in a year, now we have hash whose keys are months, and values arrays of dates for a given month.
The only problem we have is that
map
returns an array and not a hash. Thats why we "surround" whole expression byHash[]
, which makes a hash out of array of pairs, in our case pairs[year, hash_of_dates_by_month]
.Sorry if the explanation sounds confusing, I found harder to explain functional expressions than imperative, because of the nesting. :(
这让您非常接近,您只需将数字月份数字更改为文本月份名称:
This gets you pretty close, you just need to change the numerical month number into a textual month name: