We are given the following (simplified from the arrays given in the question and with one hash added to arr2):
arr1 = [
{"Date"=>"2019-07-01", "Country"=>"US", "Price"=>"11.22", "Tax"=>"8.55"},
{"Date"=>"2019-07-01", "Country"=>"US", "Price"=>"16.66", "Tax"=>"6.55"},
{"Date"=>"2019-06-30", "Country"=>"US", "Price"=>"17.85", "Tax"=>"7.12"},
{"Date"=>"2019-07-02", "Country"=>"UK", "Price"=>"14.22", "Tax"=>"4.32"}
]
arr2 = [
{"Date"=>"2019-07-01", "Price"=>"11.34", "Tax"=>"3.44"},
{"Date"=>"2019-07-01", "Price"=>"14.33", "Tax"=>"5.41"},
{"Date"=>"2019-07-02", "Price"=>"10.22", "Tax"=>"2.34"},
{"Date"=>"2019-07-03", "Price"=>"14.67", "Tax"=>"3.14"}
]
We will need a list of dates that are values of "Date" in the hashes in arr1.
dates1 = arr1.map { |g| g["Date"] }.uniq
#=> ["2019-07-01", "2019-06-30", "2019-07-02"]
Now convert arr2 to an array of those elements h in arr2 for which h["Date"] is in dates1, with all keys other than "Price" and "Tax" removed from each hash retained, and with the values of those two keys converted to string representations of their values negated:
a2 = arr2.each_with_object([]) do |g,arr| arr <<
{ "Date"=>g["Date"], "Price"=>"-" << g["Price"], "Tax" =>"-" << g["Tax"] } if
dates1.include?(g["Date"])
end
#=> [{"Date"=>"2019-07-01", "Price"=>"-11.34", "Tax"=>"-3.44"},
# {"Date"=>"2019-07-01", "Price"=>"-14.33", "Tax"=>"-5.41"},
# {"Date"=>"2019-07-02", "Price"=>"-10.22", "Tax"=>"-2.34"}]
We now loop over all elements of arr1 and a2 to create hash with keys the values of "Date", with values of "Price" and "Tax" aggregated. Once that is done we extract the value of the hash that has been constructed.
(arr1 + a2).each_with_object({}) do |g,h|
h.update(g["Date"]=>g) do |_,merged_hash,hash_to_merge|
merged_hash.merge(hash_to_merge) do |k,merged_str,str_to_merge|
["Price", "Tax"].include?(k) ? "%.2f" %
(merged_str.to_f + str_to_merge.to_f) : merged_str
end
end
end.values
#=> [{"Date"=>"2019-07-01", "Country"=>"US", "Price"=>"2.21", "Tax"=>"6.25"},
# {"Date"=>"2019-06-30", "Country"=>"US", "Price"=>"17.85", "Tax"=>"7.12"},
# {"Date"=>"2019-07-02", "Country"=>"UK", "Price"=>"4.00", "Tax"=>"1.98"}]
In this last step the receiver of values is found to be the hash:
{"2019-07-01"=>{"Date"=>"2019-07-01", "Country"=>"US",
"Price"=>"2.21", "Tax"=>"6.25"},
"2019-06-30"=>{"Date"=>"2019-06-30", "Country"=>"US",
"Price"=>"17.85", "Tax"=>"7.12"},
"2019-07-02"=>{"Date"=>"2019-07-02", "Country"=>"UK",
"Price"=>"4.00", "Tax"=>"1.98"}}
Notice that the result would be the same if arr[1]["Country"]=>"Canada". I've assumed that would not be a problem or could not occur.
The last step uses versions of the methods Hash#update (a.k.a. merge!) and Hash#merge that employ a hash to determine the values of keys that are present in both hashes being merged.
The values of the block variables (|_,merged_hash,hash_to_merge| and |k,merged_str,str_to_merge|) are explained in the docs. The first block variable is the common key (_ and k). I've represented the first of these with an underscore to signal to the reader that it is not used in the block calculation (a common convention). The second block variable is the value of the key in the hash being built (merged_hash and merged_str). The third block variable is the value of the key in the hash being merged (merged_hash and str_to_merge).