Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to merge two hashes that have same keys in ruby

Tags:

ruby

hash

I have a two hashes that should have same keys like:

a = {a: 1, b: 2, c: 3}
b = {a: 2, b: 3, c: 4}

And I want to sum up each values like this:

if a.keys == b.keys
  a.values.zip(b.values).map{|a, b| a+b}
end

But this code doesn't work if the order of keys are different like b = {a: 2, c: 4, b: 3}.

How can I write the code taking into account about order of keys?

like image 285
ironsand Avatar asked Jul 08 '14 14:07

ironsand


People also ask

How do you combine hashes in Ruby?

We can merge two hashes using the merge() method. When using the merge() method: Each new entry is added to the end. Each duplicate-key entry's value overwrites the previous value.

How do you know if two hashes are equal Ruby?

Equality—Two hashes are equal if they each contain the same number of keys and if each key-value pair is equal to (according to Object#== ) the corresponding elements in the other hash. The orders of each hashes are not compared.

Can a hash have multiple values Ruby?

Each key can only have one value. But the same value can occur more than once inside a Hash, while each key can occur only once.

How do you remove a key from a hash in Ruby?

Ruby | Hash delete() function delete() is an Hash class method which deletes the key-value pair and returns the value from hash whose key is equal to key. Return: value from hash whose key is equal to deleted key.


2 Answers

Use Hash#merge or Hash#merge!:

a = {a: 1, b: 2, c: 3}
b = {a: 2, c: 4, b: 3}
a.merge!(b) { |k, o, n| o + n }
a # => {:a=>3, :b=>5, :c=>7}

The block is called with key, old value, new value. And the return value of the block is used as a new value.

like image 69
falsetru Avatar answered Sep 22 '22 10:09

falsetru


If you're using Active Support (Rails), which adds Hash#transform_values, I really like this easy-to-read solution when you have n hashes:

hashes = [hash_1, hash_2, hash_3] # any number of hashes
hashes.flat_map(&:to_a).group_by(&:first).transform_values { |x| x.sum(&:last) }

like image 34
akb Avatar answered Sep 21 '22 10:09

akb