2012-06-08 164 views
54

例如,我有一個哈希陣列哈希散列

a = [{a: :b}, {c: :d}] 

什麼是將其轉換成這種最好的方式的陣列?

{a: :b, c: :d} 

回答

94

您可以使用

a.reduce Hash.new, :merge 

直接產生

{:a=>:b, :c=>:d} 

注意,在碰撞的情況下,順序很重要。後者的哈希值覆蓋前面的映射,例如參見:

[{a: :b}, {c: :d}, {e: :f, a: :g}].reduce Hash.new, :merge # {:a=>:g, :c=>:d, :e=>:f} 
+25

'Hash.new',或者朋友喜歡打電話給他,'{}':-)儘管我喜歡純粹的功能性解決方案,但請注意'merge'會在每次迭代時創建一個新的散列;我們可以使用'update'來代替(它不會混淆輸入哈希值,這是重點):'hs.reduce({},:update)' – tokland

+0

做得很好 – Aeramor

+0

@tokland,將您的評論作爲單獨發佈答案 - 它應該獲得更多的知名度 – Jason

19

這兩行是等同的:

total_hash = hs.reduce({}) { |acc_hash, hash| acc_hash.merge(hash) } 
total_hash = hs.reduce({}, :merge) 

注意Hash#merge創建在每次迭代一個新的哈希值,如果你正在建設一個這可能是一個問題大哈希。在這種情況下,使用update代替:

total_hash = hs.reduce({}, :update) 

另一種方法是將哈希轉化爲對,然後建立最終的哈希:

total_hash = hs.flat_map(&:to_a).to_h 
18

您可以使用.inject

a.inject(:merge) 
#=> {:a=>:b, :c=>:d} 

Demonstration

它從兩個合併的每個迭代啓動一個新的散列。爲了避免這種情況,你可以使用破壞性:merge!(或:update,這是相同的):

a.inject(:merge!) 
#=> {:a=>:b, :c=>:d} 

Demonstration

0

試試這個

a.inject({}){|acc, hash| acc.merge(hash)} #=> {:a=>:b, :c=>:d}