2011-12-06 160 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 }