2016-10-31 15 views
1

Via Auswahl erhalte ich die folgende Antwort:Zusammenfassung mehrerer Hashes in Ruby

=> [{: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 diesem Beispiel gibt es zwei Gruppen von Hashes. Es könnte mehr Ergebnisse geben aber die Daten werden jedes Mal gleich sein.

Gibt es eine einfache Möglichkeit, es mit dem folgenden Ergebnis zu kombinieren?

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

Für Arrays könnte ich transpose.map {|x| x.reduce(:+)} verwenden, aber nicht für Hashes. Gibt es eine ähnliche Lösung für Hashes?

+0

beachten Sie, dass Sie eine Reihe von Hashes haben :) – niceman

+0

Willkommen bei Stack Overflow. Bitte lesen Sie "[fragen]" und "[mcve]". Deine Frage ist verfrüht. Sie sollten uns Ihren Versuch zeigen, zusammen mit einer Frage zu dem spezifischen Problem. Sie bitten uns, Ihnen den Code zu geben, was zu mehreren verschiedenen Möglichkeiten führt, und normalerweise passt keiner zu Ihrem aktuellen Code, was dazu führt, dass Sie ihn einschärfen müssen. –

+1

Vielen Dank für den Greenie, aber in Zukunft sollten Sie bitte warten länger, bevor Sie eine Auswahl treffen. Eine schnelle Auswahl kann andere Antworten entmutigen und andere, die noch an ihren Antworten arbeiten, kurzschließen. Es gibt keine Eile. Viele warten hier mindestens ein paar Stunden, bevor sie eine Auswahl treffen (manche warten viel länger). –

Antwort

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

Die Schritte sind wie folgt.

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

das ist die lösung! Danke –

2

das Array von Hashes in der Antwort gegeben:

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

Sie inject können sie beide und erhalten das Ergebnis, das Sie in Ihrem Beispiel geliefert zu kombinieren:

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

Ihr Ergebnis sieht nun wie Beispiel:

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

Anstelle von 'inject' würde ich' each_with_object' empfehlen. Es führt zu einem etwas saubereren Code. Auch, Memo = Hash.new {| h, k | h [k] = []} 'wird die Notwendigkeit entfernen, den Hash-Code vorab zu überprüfen und leere Hashes zuzuweisen. –

Verwandte Themen