2, "Y"=>1...">

Subtracting hashes in ruby

I have 2 hashes (which will later be converted to an array, not sure if this is relevant):

Hash1 = {"X"=>2, "Y"=>1, "Z"=>1}

Hash2 = {"X"=>1, "Y"=>1}

      

I need to subtract them as (Hash3 = Hash1 - Hash2) and I want the result of Hash3, in this case:

Hash3 = {"X"=>1, "Y"=>0, "Z"=>1}

      

All the examples and answers I have seen resulted in results where the key that mattered was 0 (Y) was missing from the resulting hash, which is not what I want.

I am using Ruby 2.3.3 and Rails 5.0

+3


source to share


3 answers


You can merge

:

h1 = {"X"=>2, "Y"=>1, "Z"=>1}
h2 = {"X"=>1, "Y"=>1}

h1.merge(h2) { |k, v1, v2| v1 - v2 }
#=> {"X"=>1, "Y"=>0, "Z"=>1}

      

Whenever a key is present in both hashes, the block is called to determine the new value.


As a result, this behavior will not result in negative values ​​if the key is only present in h2

:



h1 = {"X"=>2, "Y"=>1}
h2 = {"X"=>1, "Y"=>1, "Z"=>1}

h1.merge(h2) { |k, v1, v2| v1 - v2 }
#=> {"X"=>1, "Y"=>0, "Z"=>1}

      

You can expect:

#=> {"X"=>1, "Y"=>0, "Z"=>-1}

      

This is what tadman's solution will return.

+12


source


It's not too difficult if you split it into two steps:

def hash_sub(a, b)
  (a.keys + b.keys).uniq.map do |k|
    [ k, a[k].to_i - b[k].to_i ]
  end.to_h
end

hash_sub({"X"=>2, "Y"=>1, "Z"=>1}, {"X"=>1, "Y"=>1})
# => {"X"=>1, "Y"=>0, "Z"=>1}

      



The first step is to compute all possible (unique) keys by concatenating the keys from the two hashes, and then convert to a new hash by subtracting one from the other, forcing the conversion to an integer c .to_i

.

+3


source


You can match them as well (but the merge solution is better since it takes care of getting the values ​​from 2 even if the key is not present in 1):

hash3 = hash1.map{|k,v| { k: (v-(hash2[k.to_s] || 0)) }.stringify_keys }

      

This will give an array

0


source







All Articles