2013-09-25 44 views
4

我有一個哈希數組,想總結選定的值。我知道如何總結他們或他們中的一個,但不知道如何選擇多個鍵。Ruby:總結選定的哈希值

即:

[{"a"=>5, "b"=>10, "active"=>"yes"}, {"a"=>5, "b"=>10, "active"=>"no"}, {"a"=>5, "b"=>10, "action"=>"yes"}] 

要我用概括所有的人:

t = h.inject{|memo, el| memo.merge(el){|k, old_v, new_v| old_v + new_v}} 
=> {"a"=>15, "b"=>30, "active"=>"yesnoyes"} # I do not want 'active' 

綜上所述一個關鍵,我做的:

h.map{|x| x['a']}.reduce(:+) 
=> 15 

如何去總結鍵「a」和「b」的值?

+0

爲什麼不只是做'h.map {| X | x ['a'] + x ['b']} .reduce(:+)'? –

+0

感謝@kardeiz您的評論。但它是返回45.我應該已經更清楚了...我想要的是: {'a'=> 15,'b'=> 30} – Digger

回答

6

您可以使用values_at

hs = [{:a => 1, :b => 2, :c => ""}, {:a => 2, :b => 4, :c => ""}] 
keys = [:a, :b] 
hs.map { |h| h.values_at(*keys) }.inject { |a, v| a.zip(v).map { |xy| xy.compact.sum }} 
# => [3, 6] 

如果所有所需的密鑰具有值會更短:

hs.map { |h| h.values_at(*keys) }.inject { |a, v| a.zip(v).map(&:sum) } 
# => [3, 6] 

如果你想Hash回:

Hash[keys.zip(hs.map { |h| h.values_at(*keys) }.inject{ |a, v| a.zip(v).map(&:sum) })] 
# => {:a => 3, :b => 6} 
+0

'values_at'是完美的起點。 +1 –

+1

謝謝@VictorMoroz,你的Hash例子就像一個魅力。 你能解釋你在那裏做什麼嗎? 再次感謝, – Digger

2

這是怎麼回事?

h = [{"a"=>5, "b"=>10, "active"=>"yes"}, {"a"=>5, "b"=>10, "active"=>"no"}, {"a"=>5, "b"=>10, "action"=>"yes"}] 
p h.map{|e| e.reject{|k,v| %w(active action).include? k } }.inject{|memo, el| memo.merge(el){|k, old_v, new_v| old_v + new_v}} 
# >> {"a"=>15, "b"=>30} 
3

我會做這樣的事情:

a.map { |h| h.values_at("a", "b") }.transpose.map { |v| v.inject(:+) } 
#=> [15, 30] 

一步一步:

a.map { |h| h.values_at("a", "b") } #=> [[5, 10], [5, 10], [5, 10]] 
.transpose       #=> [[5, 5, 5], [10, 10, 10]] 
.map { |v| v.inject(:+) }   #=> [15, 30] 
+1

謝謝@Stefan您的評論。 如何將密鑰添加到返回的數組中。我期待它返回: {'a'=> 15,'b'=> 30} – Digger

+0

'Hash [keys.zip(values)]' 'Hash [[「a」,「b」]。zip([15,30])]'' – Stefan