我想總結數組中相同項的總數。如何使用不同的散列求和數組中的值
我有一個數組作爲
[{"a"=>1},{"b"=>2},{"c"=>3},{"a"=>2},{"b"=>4}]
我想要得到的結果作爲
[{"a"=>3},{"b"=>6},{"c"=>3}]
哪一種方法可以做到這一點?
我想總結數組中相同項的總數。如何使用不同的散列求和數組中的值
我有一個數組作爲
[{"a"=>1},{"b"=>2},{"c"=>3},{"a"=>2},{"b"=>4}]
我想要得到的結果作爲
[{"a"=>3},{"b"=>6},{"c"=>3}]
哪一種方法可以做到這一點?
如果:
array = [{"a"=>1},{"b"=>2},{"c"=>3},{"a"=>2},{"b"=>4}]
,那麼你可以這樣做:
array.inject(Hash.new{|h,k| h[k] = 0})
{ |h, a| k, v = a.flatten; h[k] += v; h }.
map{|arr| Hash[*arr] }
#=> [{"a"=>3}, {"b"=>6}, {"c"=>3}]
或:
array.each_with_object(Hash.new{|h,k| h[k] = 0})
{ |a, h| k, v = a.flatten; h[k] += v }.
map{|arr| Hash[*arr] }
#=> [{"a"=>3}, {"b"=>6}, {"c"=>3}]
有很多方法可以做到這一點。看到一些甚至是一些可能不尋常和/或不是特別有效的東西是有益的。
這裏是另一種方式:
arr = [{"a"=>1},{"b"=>2},{"c"=>3},{"a"=>2},{"b"=>4}]
arr.flat_map(&:keys)
.uniq
.map { |k| { k=>arr.reduce(0) { |t,g| t + (g.key?(k) ? g[k] : 0) } } }
#=> [{"a"=>3}, {"b"=>6}, {"c"=>3}]
由於nil.to_i => 0
,我們可以改爲寫reduce
的塊爲:
{ |t,g| t+g[k].to_i }
要在不是一比一的方式來轉換集合每一次,它是#reduce
工作。對於一對一轉換,我們使用#map
。
array.reduce({}) { |h, acc| acc.merge(h) {|_k, o, n| o+n } }.zip.map(&:to_h)
# => [{"b"=>6}, {"a"=>3}, {"c"=>3}]
在這裏,我們使用與初始值{}
,其被傳遞到塊作爲acc
參數減少,然後我們使用#merge
具有手動「解決衝突」。這意味着僅當我們試圖合併的密鑰已經存在於方法接收器acc
中時纔會調用該塊。之後,我們將哈希分解爲哈希數組。
你需要添加'。{{| k,v | {k => v}}'或者類似於結尾的東西,將結果轉換爲指定的形式(散列數組)。 – 2014-10-02 06:55:49
它應該產生:'[{「a」=> 3},{「b」=> 6},{「c」=> 3}]'不是'{「b」=> 6,「a」=> 3,「c」=> 3}'。我認爲你需要做一些像@CarySwoveland提到的事情。 – Surya 2014-10-02 07:02:01
這也是一個好方法。謝謝。 – 2014-10-02 09:50:24
它可以如下
array.group_by { |h| h.keys.first }.
values.
map {|x| x.reduce({}) { |h1, h2| h1.merge(h2) { |_, o, n| o + n } }
#=> [{"a"=>3}, {"b"=>6}, {"c"=>3}]
'#each_with_object'就是我要找如果使用或不使用任何一個來完成。 :-)但是你做到了,所以你節省了我的時間..:P +1 – 2014-10-02 08:05:45
1.你不需要'to_a'。 (爲什麼?)。 2.你不需要'; h'與'each_with_object'(這就是@Arup建議後者的原因)。 3.「arr」是一個合適的名字嗎?該格式大大改善。 – 2014-10-02 15:26:44
@CarySwoveland是的正是..這就是爲什麼我不使用'#注入',如果我不被迫.. .. P – 2014-10-02 15:33:21