2011-12-06 113 views
6

说我有最好的方法:在Rails中,什么是压缩哈希到嵌套哈希

[ 
    { :user_id => 1, :search_id => a}, 
    { :user_id => 1, :search_id => b}, 
    { :user_id => 2, :search_id => c}, 
    { :user_id => 2, :search_id => d} 
] 

,我想结束了:

[ 
    { :user_id => 1, :search_id => [a,b]}, 
    { :user_id => 2, :search_id => [c,d]} 
] 

什么是最好的如何做到这一点?

回答

7

的确很奇怪。无论如何

[ { :user_id => 1, :search_id => "a"}, 
    { :user_id => 1, :search_id => "b"}, 
    { :user_id => 2, :search_id => "c"}, 
    { :user_id => 2, :search_id => "d"} ] \ 
    .map{ |h| h.values_at(:user_id, :search_id) } \ 
    .group_by(&:first) \ 
    .map{ |k, v| { :user_id => k, :search_id => v.map(&:last) } } 
+0

哦,漂亮多了! +1 – Matchu

0

首先,我觉得这里的干净的输出结构,允许用户ID是哈希键和搜索ID列表是值:

{ 
    1 => [a, b], 
    2 => [c, d] 
} 

有可能是使用一个聪明的方法Rails助手可以获得这种结构,但手动操作也不错,可以:

output = {} 
input.each do |row| 
    key = row[:user_id] 
    value = row[:search_id] 

    output[key] ||= [] 
    output[key] << value 
end 
0

我同意Matchus的数据表示,只是想为它建议一个较短的版本(输入是初始数组)。

input.each.with_object(Hash.new {|h,k| h[k] = []}) do |k,o| 
    o[k[:user_id]] << k[:search_id] 
end 

编辑:这是红宝石> 1.9

1
array.group_by{|x| x[:user_id] }.values.map do |val| 
    { user_id: val.first[:user_id], 
    search_id: val.inject([]){|me, el| me << el[:search_id]} } 
end 
0
input.inject({}) do 
    |m, h| (m[h[:user_id]] ||= []) << h[:search_id]; m 
end.inject([]) { |m, (k, v)| m << { :user_id => k, :search_id => v }; m }