Ricky Spanish Ricky Spanish - 1 month ago 6
Ruby Question

Summary of multiple hashes in Ruby

Via selection I get the following response:

=> [{:month=>[3, 3, 9, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
:dates=>["30.10:", "29.10:", "28.10:", "27.10:", "26.10:", "25.10:", "24.10:", "23.10:", "22.10:", "21.10:", "20.10:", "19.10:", "18.10:", "17.10:", "16.10:", "15.10:", "14.10:", "13.10:", "12.10:", "11.10:", "10.10:", "09.10:", "08.10:", "07.10:", "06.10:", "05.10:", "04.10:", "03.10:", "02.10:", "01.10:"]},
{:month=>[1, 3, 5, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
:dates=>["30.10:", "29.10:", "28.10:", "27.10:", "26.10:", "25.10:", "24.10:", "23.10:", "22.10:", "21.10:", "20.10:", "19.10:", "18.10:", "17.10:", "16.10:", "15.10:", "14.10:", "13.10:", "12.10:", "11.10:", "10.10:", "09.10:", "08.10:", "07.10:", "06.10:", "05.10:", "04.10:", "03.10:", "02.10:", "01.10:"]}]


In this example there are two groups of hashes. There could be more results
but the dates will be the same every time.

Is there an easy way to combine it to the following result?

[{:month=>[4, 6, 14, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
:dates=>["30.10:", "29.10:", "28.10:", "27.10:", "26.10:", "25.10:", "24.10:", "23.10:", "22.10:", "21.10:", "20.10:", "19.10:", "18.10:", "17.10:", "16.10:", "15.10:", "14.10:", "13.10:", "12.10:", "11.10:", "10.10:", "09.10:", "08.10:", "07.10:", "06.10:", "05.10:", "04.10:", "03.10:", "02.10:", "01.10:"]}


For Arrays I could use
transpose.map {|x| x.reduce(:+)}
but not for hashes.
Is there a similar solution for hashes?

Answer
arr = [{ :month=>[3, 3, 9], :dates=>["30.10:", "29.10:"] },
       { :month=>[1, 3, 5], :dates=>["30.10:", "29.10:"] },
       { :month=>[2, 4, 6], :dates=>["30.10:", "29.10:"] }]

{ :month=>arr.map { |h| h[:month] }.transpose.map { |a| a.reduce(:+) },
  :dates=>arr.first[:dates] }
  #=> {:month=>[6, 10, 20], :dates=>["30.10:", "29.10:"]} 

The steps are as follows.

a = arr.map { |h| h[:month] }
  #=> [[3, 3, 9], [1, 3, 5], [2, 4, 6]] 
b = a.transpose
  #=> [[3, 1, 2], [3, 3, 4], [9, 5, 6]] 
c = b.map { |a| a.reduce(:+) }
  #=> [6, 10, 20] 
d = arr.first
  #=> {:month=>[3, 3, 9], :dates=>["30.10:", "29.10:"]} 
e = d[:dates]
  #=> ["30.10:", "29.10:"] 
{ :month=>c, :dates=>e }
  #=> {:month=>[6, 10, 20], :dates=>["30.10:", "29.10:"]} 
Comments