Merging two hashes with the mean values of each key if both hashes exist There are two methods, hash1 and hash2, that return hashes or nil. The hashes have the same keys. I want to merge them with their mean value only if both methods have hashes.

(I added Array#mean to calculate the average value of an array).

def merged_hashes
    return if hash1.nil? &amp;&amp; hash2.nil?
    return hash2 if hash1.nil?
    return hash1 if hash2.nil?
    hash1.merge(hash2) do |key, v1, v2|
      [v1, v2].compact.mean
    end
end


Is there more succinct way to write this?
There are many ways to do this, but all have two common elements. Firstly, since hash1 and hash2 are methods, you want to only call those methods once, which means saving the return values in variables:

h1 = hash1
h2 = hash2


Secondly, there are four possible courses of action, depending on the values of h1 and h2. You may wish to represent these with a case statement:

def merged_hashes(hash1,hash2)
  h1 = hash1
  h2 = hash2
  case [h1.is_a?(Hash), h2.is_a?(Hash)]
  when [false, false] then nil
  when [false, true]  then h2
  when [true, false]  then h1
  else compute_avg(h1, h2)
  end
end


Note that it is necessary to compute both h1 and h2 even if the first one computed is found to not be a hash.

All that remains is to construct the method compute_avg. Here are three ways that might be done:

Merge h1 and h2, using the form of Hash#merge that employs a block to determine the values of keys that are present in both hashes being merged, which here is all keys.

compute_avg(h1,h2)
  h1.merge(h2) { |_, v1, v2| [v1, v2].compact.mean }
end


You used merge in this way in your solution.

Extract values of h2 and send Enumerable#each_with_object to h1 to build the desired hash

compute_avg(h1,h2)
  values2 = h2.values
  h1.each_with_object({}) { |(k,v1),h| h[k] = [v1, values2.shift].compact.mean }
end


Extract the values of h1 and h2, compute their averages, element-by-element, then construct the hash to be returned

compute_avg(h1,h2)
  keys = h1.keys
  averages = { h1.values.zip(h2.values).map { |x1,x2| [x1, x2].compact.mean  } }
  keys.zip(averages).to_h
end