如何将哈希数组转换为有序哈希?

时间:2012-01-21 21:39:42

标签: ruby-on-rails ruby arrays hash

如果我有一组哈希值,每个哈希值都有一个日期键:

[
    {: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

4 个答案:

答案 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)]