简体   繁体   中英

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(:+)} transpose.map {|x| x.reduce(:+)} but not for hashes. Is there a similar solution for hashes?

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:"]} 

Given the array of hashes in the response:

@hashes = [{: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:"]}]

You can use inject to combine them both and get the result you supplied in your example:

result = @hashes.inject({}) do |memo, hash|
  memo[:month] ||= []
  memo[:dates] ||= []
  memo[:month] += hash[:month]
  memo[:dates] += hash[:dates]
  memo
end

Now result looks like your example:

result == {
  :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, 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:", "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:"]
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM