2017-06-30 4 views
-2

Ich habe zwei ähnliche Hashes. Die erste sieht aus wie:Was ist der beste Weg, Hashes zusammenzuführen?

{'1'=> 
    {'ab'=>{'a'=>1, 'b'=>4}, 
    {'bc'=>{'b'=>2, 'c'=>1}, 
    ... 
} 

Das zweite recht ähnlich ist:

{'1'=> 
    {'ab'=>{'v'=>1}, 
    {'bc'=>{'v'=>2}, 
    ... 
} 

Ich möchte diese verschmelzen wie:

{'1'=> 
    {'ab'=>{'a'=>1, 'b'=>4, 'v'=>1}, 
    {'bc'=>{'b'=>2, 'c'=>1, 'v'=>2}, 
    ... 
} 

Was ist die beste Art und Weise zu tun Das?

+0

Gibt es mehr als einen Schlüssel auf der zweiten Ebene? Sie sollten wahrscheinlich die Syntaxfehler beheben, um in dieser Hinsicht klarer zu sein. – tadman

Antwort

1

Versuchen Sie Hash#deep_merge von ActiveSupport. https://apidock.com/rails/Hash/deep_merge

Wenn Sie nicht auf active_support gem angewiesen sind oder Core-Klassen nicht affektieren möchten, können Sie den Algorithmus einfach von der AS kopieren und an Ihre Bedürfnisse anpassen.

# File activesupport/lib/active_support/core_ext/hash/deep_merge.rb, line 21 
    def deep_merge!(other_hash, &block) 
    other_hash.each_pair do |current_key, other_value| 
     this_value = self[current_key] 

     self[current_key] = if this_value.is_a?(Hash) && other_value.is_a?(Hash) 
     this_value.deep_merge(other_value, &block) 
     else 
     if block_given? && key?(current_key) 
      block.call(current_key, this_value, other_value) 
     else 
      other_value 
     end 
     end 
    end 

    self 
    end 

UPDATE:

Ich bin mir nicht sicher, warum die Antwort Downvoted wurde. Hier ist deep_merge in Aktion:

[10] pry(main)> a = {'1'=> 
[10] pry(main)* {'ab'=>{'a'=>1, 'b'=>4}, 
[10] pry(main)* 'bc'=>{'b'=>2, 'c'=>1}} 
[10] pry(main)* }; 
[11] pry(main)> 
[12] pry(main)> b = {'1'=> 
[12] pry(main)* {'ab'=>{'v'=>1}, 
[12] pry(main)* 'bc'=>{'v'=>2}} 
[12] pry(main)* }; 
[13] pry(main)> 
[14] pry(main)> a.deep_merge(b) 
=> {"1"=>{"ab"=>{"a"=>1, "b"=>4, "v"=>1}, "bc"=>{"b"=>2, "c"=>1, "v"=>2}}} 
[15] pry(main)> 

Genau was OP braucht.

+0

Ja. heutzutage sollen wir von dort aus eine ganze Rails oder Copy-Paste eine 15-LOC-Methode bringen, anstatt selbst einen trivialen Einzeiler zu schreiben. – mudasobwa

+0

Ich weiß, ich weiß. – DNNX

3

Für diese einfachen Fall:

h1.merge(h2) do |_, v1, v2| 
    v1.merge(v2) { |_, v1, v2| v1.merge(v2) } 
end 
#⇒ {"1"=>{"ab"=>{"a"=>1, "b"=>4, "v"=>1}, 
#   "bc"=>{"b"=>2, "c"=>1, "v"=>2}}} 

Beachten Sie auch, dass das, was Sie als Eingabe gebucht haben sind nicht gültig Rubin Objekte.

+0

Fazit: Wenn 'merge' nicht hilft, rufen Sie einfach weiter an, bis Sie das gewünschte Ergebnis erhalten. – Stefan

+0

@Stefan Ich habe versucht, aber manchmal klagt der Stapel mit kryptischen "zu tief" Nachricht :) – mudasobwa

+0

Wow es ist erstaunlich für mich, dass eine Frage mit dem Titel * "Was ist der beste Weg, Hashes zusammenführen?" * Führte zu Hash # fusionieren. Wer würde es thunk? Vielleicht hättest du 'Hash # update' verwenden sollen, um cool zu sein. Nebenbei bemerkt, obwohl Ihre pipe-Variablen wahrscheinlich unterschiedliche Namen haben sollten, da sie die Referenz innerhalb einer doppelten Iteration verwirren. – engineersmnky

Verwandte Themen