2014-09-27 192 views
1

我想借此陣列哈希值的數組...合併和鞏固哈希

items => [{:name=>"item a", :count=>1, :contributors=>["51db6d58bd02861e96000004"]}, 
{:name=>"item b", :count=>1, :contributors=>["51db6d58bd02861e96000004"]}, 
{:name=>"item a", :count=>1, :contributors=>["51db6d58bd02861e96000004"]}, 
{:name=>"item b", :count=>1, :contributors=>["51db6d58bd02861e96000004"]}, 
{:name=>"item c", :count=>1, :contributors=>["51db6d58bd02861e96000004"]}, 
{:name=>"item d", :count=>1, :contributors=>["51db6d58bd02861e96000004"]}] 

,並得到一個輸出,看起來像以下...

items => [{:name=>"item a", :count=>2, :contributors=>["51db6d58bd02861e96000004", "51db6d58bd02861e96000004"]}, 
    {:name=>"item b", :count=>2, :contributors=>["51db6d58bd02861e96000004, 51db6d58bd02861e96000004"]}, 
    {:name=>"item c", :count=>1, :contributors=>["51db6d58bd02861e96000004"]}, 
    {:name=>"item d", :count=>1, :contributors=>["51db6d58bd02861e96000004"]}] 

我想要按名稱分組並統計計數,並按照上面的說明進行貢獻。我怎麼做? Group_by,減少?有人可以發表一個例子嗎?

+0

請顯示您到目前爲止嘗試了些什麼。 – 2014-09-27 03:20:26

+0

什麼是'items =>'?這部分使你的表達無效。 – sawa 2014-09-27 03:24:06

+1

你的意思是'物品= [...]'? – falsetru 2014-09-27 03:26:46

回答

2

使用Enumerable#group_by

items = [ 
    {:name=>"item a", :count=>1, :contributors=>["51db6d58bd02861e96000004"]}, 
    {:name=>"item b", :count=>1, :contributors=>["51db6d58bd02861e96000004"]}, 
    {:name=>"item a", :count=>1, :contributors=>["51db6d58bd02861e96000004"]}, 
    {:name=>"item b", :count=>1, :contributors=>["51db6d58bd02861e96000004"]}, 
    {:name=>"item c", :count=>1, :contributors=>["51db6d58bd02861e96000004"]}, 
    {:name=>"item d", :count=>1, :contributors=>["51db6d58bd02861e96000004"]} 
] 
items.group_by { |h| h[:name] }.map { |key, hs| 
    {:name => key, 
    :count => hs.inject(0) { |c, h| c + h[:count] }, 
    :contributors => hs.map { |h| h[:contributors] } 
    } 
} 

# => [{:name=>"item a", :count=>2, 
#  :contributors=>[["51db6d58bd02861e96000004"], ["51db6d58bd02861e96000004"]]}, 
#  {:name=>"item b", :count=>2, 
#  :contributors=>[["51db6d58bd02861e96000004"], ["51db6d58bd02861e96000004"]]}, 
#  {:name=>"item c", :count=>1, :contributors=>[["51db6d58bd02861e96000004"]]}, 
#  {:name=>"item d", :count=>1, :contributors=>[["51db6d58bd02861e96000004"]]}] 
+0

考慮到我最初發布了相同的解決方案(然後看到你的已經啓動了,刪除了它),+1是一件容易的事。 – 2014-09-27 04:41:47

+0

這工作完美,既然是第一個答案,我已經接受了。謝謝您的幫助。 – aressidi 2014-09-27 23:51:43

+0

祝賀100k! – 2014-09-28 01:29:08

1

我最初發布的另一種解決方案,才發現@falsetru已經公佈了幾乎相同的答案,所以這是回到繪圖板。實際上並非如此,因爲這類問題有兩種常見的攻擊方式,所以我隨後與另一種攻擊方式一起進行。

def combine(items) 
    items.each_with_object({}) do |g,h| 
    h.update({ g[:name] => g }) do |k,ov,nv| 
     { name: g[:name], count: (ov[:count] + nv[:count]), 
     contributors: (ov[:contributors] + nv[:contributors]) } 
    end 
    end.values 
end 

這使用的Hash#update(又名merge!),其採用一塊用於確定由被合併兩個散列共享的每個項中的值的形式。

注意我允許:count的值不是1:contributors的值(數組)包含多個值。

combine(items) 
#=>[{:name=>"item a", :count=>2, 
# :contributors=>["51db6d58bd02861e96000004", "51db6d58bd02861e96000004"]}, 
# {:name=>"item b", :count=>2, 
# :contributors=>["51db6d58bd02861e96000004", "51db6d58bd02861e96000004"]}, 
# {:name=>"item c", :count=>1, :contributors=>["51db6d58bd02861e96000004"]}, 
# {:name=>"item d", :count=>1, :contributors=>["51db6d58bd02861e96000004"]}] 
+0

感謝卡里,這似乎也是一個很好的方法,並很好地解釋。 – aressidi 2014-09-27 23:52:55