65

How can I merge these two hashes:

{:car => {:color => "red"}}
{:car => {:speed => "100mph"}}

To get:

{:car => {:color => "red", :speed => "100mph"}}
the Tin Man
  • 158,662
  • 42
  • 215
  • 303
skyporter
  • 847
  • 1
  • 7
  • 14

4 Answers4

79

There is a Hash#merge method:

ruby-1.9.2 > a = {:car => {:color => "red"}}
 => {:car=>{:color=>"red"}} 
ruby-1.9.2 > b = {:car => {:speed => "100mph"}}
 => {:car=>{:speed=>"100mph"}} 
ruby-1.9.2 > a.merge(b) {|key, a_val, b_val| a_val.merge b_val }
 => {:car=>{:color=>"red", :speed=>"100mph"}} 

You can create a recursive method if you need to merge nested hashes:

def merge_recursively(a, b)
  a.merge(b) {|key, a_item, b_item| merge_recursively(a_item, b_item) }
end

ruby-1.9.2 > merge_recursively(a,b)
 => {:car=>{:color=>"red", :speed=>"100mph"}} 
the Tin Man
  • 158,662
  • 42
  • 215
  • 303
Aliaksei Kliuchnikau
  • 13,589
  • 4
  • 59
  • 72
  • yes I thought that recursively will be a part of the solution, it's exactly what I need. Thanks for you help Alex – skyporter Dec 14 '11 at 10:40
  • 9
    Use `a.merge!(b)` if you want to change `a` directly. – gm2008 Jul 16 '14 at 08:34
  • 1
    maybe will help someone, if a_item is not a hash then above will fail i guess, something like this could help, it will overwrite all values in 'a' that you have specified in 'b', for instance your 'a' has some defaults and 'b' some actual runtime values. def merge_recursively(a, b) a.merge!(b) {|key, a_item, b_item| if a_item.is_a?(Hash) merge_recursively(a_item, b_item) else b_item end } end – qwebek Apr 11 '17 at 19:00
46

Hash#deep_merge

Rails 3.0+

a = {:car => {:color => "red"}}
b = {:car => {:speed => "100mph"}}
a.deep_merge(b)
=> {:car=>{:color=>"red", :speed=>"100mph"}} 

Source: https://speakerdeck.com/u/jeg2/p/10-things-you-didnt-know-rails-could-do Slide 24

Also,

http://apidock.com/rails/v3.2.13/Hash/deep_merge

Andrei
  • 1,121
  • 8
  • 19
19

You can use the merge method defined in the ruby library. https://ruby-doc.org/core-2.2.0/Hash.html#method-i-merge


Example

h1={"a"=>1,"b"=>2} 
h2={"b"=>3,"c"=>3} 
h1.merge!(h2)

It will give you output like this {"a"=>1,"b"=>3,"c"=>3}

Merge method does not allow duplicate key, so key b will be overwritten from 2 to 3.

To overcome the above problem, you can hack merge method like this.

h1.merge(h2){|k,v1,v2|[v1,v2]}

The above code snippet will be give you output

{"a"=>1,"b"=>[2,3],"c"=>3}
n4m31ess_c0d3r
  • 3,028
  • 5
  • 26
  • 35
Mukesh Kumar Gupta
  • 1,567
  • 20
  • 15
4
h1 = {:car => {:color => "red"}}
h2 = {:car => {:speed => "100mph"}}
h3 = h1[:car].merge(h2[:car])
h4 = {:car => h3}
bor1s
  • 4,081
  • 18
  • 25