如果我有一组哈希值,每个哈希值都有一个日期键:
[
{:day=>4,:name=>'Jay'},
{:day=>1,:name=>'Ben'},
{:day=>4,:name=>'Jill'}
]
将其转换为带有排序日期值的哈希作为键的最佳方法是什么:
{
:1=>[{:day=>1,:name=>'Ben'}],
:4=>[{:day=>4,:name=>'Jay'},{:day=>4,:name=>'Jill'}]
}
我正在使用Ruby 1.9.2和Rails 3.1.1
答案 0 :(得分:4)
就个人而言,我不打扰“排序”键(这相当于在Ruby 1.9中按入口时间排序),直到我真正需要。然后,您可以使用group_by
:
arr = [{:day=>4,:name=>'Jay'}, {:day=>1,:name=>'Ben'}, {:day=>4,:name=>'Jill'}]
arr.group_by { |a| a[:day] }
=> {4=>[{:day=>4, :name=>"Jay"}, {:day=>4, :name=>"Jill"}],
1=>[{:day=>1, :name=>"Ben"}]}
相反,在实际需要时对键进行排序。
答案 1 :(得分:1)
假设您调用的数组是list
,这是使用reduce
方法的一种方式:
list.reduce({}) { |hash, item|
(hash[item[:day]] ||= []) << item; hash
}
这是另一个使用map
方法的方法,但你必须携带一个持有人变量:
hash = {}
list.each { |item|
(hash[item[:day]] ||= []) << item
}
在变量foo
中有未分类的哈希后,您可以将其排序为
Hash[foo.sort]
答案 2 :(得分:0)
简单回答:
data = [
{:day=>4,:name=>'Jay'},
{:day=>1,:name=>'Ben'},
{:day=>4,:name=>'Jill'}
]
#expected solution
sol = {
1=>[{:day=>1,:name=>'Ben'}],
4=>[{:day=>4,:name=>'Jay'},{:day=>4,:name=>'Jill'}]
}
res = {}
data.each{|h|
res[h[:day]] ||= []
res[h[:day]] << h
}
p res
p res == sol #check value
p res.keys == sol.keys #check order
此解决方案的问题:散列未按要求排序。 (同样的问题有Anurags solution)。
所以你必须稍微修改一下答案:
res = {}
data.sort_by{|h| h[:day]}.each{|h|
res[h[:day]] ||= []
res[h[:day]] << h
}
p res
p res == sol #check value
p res.keys == sol.keys #check order
答案 3 :(得分:0)
在Rails中,您可以使用OrderedHash
:
ActiveSupport::OrderedHash[arr.group_by { |a| a[:day] }.sort_by(&:first)]
更新:事实上,在Ruby 1.9中,哈希是有序的,因此不需要使用ActiveSupport
扩展名:
Hash[arr.group_by { |a| a[:day] }.sort_by(&:first)]