2011-12-06 11 views
6

कहो मैं इस राशि में एक हैश संकुचित करने के लिए क्या है:रेल में, सबसे अच्छा तरीका है एक नेस्टेड हैश

[ 
    { :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 की सूची मूल्यों होने के लिए अनुमति देने के लिए है:

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

का उपयोग कर एक चतुर तरीका नहीं हो सकता है सहायकों रेल इस संरचना प्राप्त करने के लिए, लेकिन यह मैन्युअल रूप से ऐसा करने के लिए बहुत बुरा नहीं है, या तो:

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 } 
है
संबंधित मुद्दे