简体   繁体   中英

How to deep merge two nested Hashes of Arrays in Ruby?

I'm trying to merge two nested array of array of hashes.

h1 = {:f => [{:f => [{:name => "a","type"=>"t",:mode=>"n"},{:name => "b","type"=>"t",:mode=>"n"}], :name => "p",:t=>"r"}]}

h2 = {:f => [{:f => [{:name => "a","type"=>"t",:mode=>"n"},{:name => "c","type"=>"t",:mode=>"n"}], :name => "p",:t=>"r"}]}

Here's what I'm expecting as output.

{:f => [{:f => [{:name => "a","type"=>"t",:mode=>"n"},{:name => "b","type"=>"t",:mode=>"n"},{:name => "c","type"=>"t",:mode=>"n"}], :name => "p",:t=>"r"}]}

I've used deep_merge & deep_merge! However that doesn't give me desired outcome. Appreciate any pointers.

Thanks, Navneet

As noted in comment there will be no general solution for what you want. The code below should work for your nesting structure (and is extremely ugly):

{f: [h1[:f].first.deep_merge(h2[:f].first) { |key, old, new| old == new ? new : (Array.wrap(old) + Array.wrap(new)).uniq }]}

The question is - why do you need to do this? Most likely there is better way to do what you are trying to achieve by this.

Here's what I wrote to solve it:

    class ::Array
     def mergeFields(second)
      second.each do |sElem|
       match = false
       self.each do |fElem|
        puts "Comparing: #{sElem[:name]} and #{fElem[:name]}"
        if sElem[:name] == fElem[:name]
         if !sElem[:fields].nil? && !fElem[:fields].nil? && sElem[:fields].is_a?(Array) && fElem[:fields].is_a?(Array)
          fElem[:fields].mergeFields(sElem[:fields])
         end  
         match = true
         break
        end
       end
       if match == false
        self << sElem  
       end 
      end
     end
    end

    h1 = {:fields => [{:fields => [{:name => "a","type"=>"t",:mode=>"n"},{:name => "b","type"=>"t",:mode=>"n"}], :name => "p",:t=>"r"},{:name => "e", :t => "s", :m => "n"}]}


    h2 = {:fields => [{:fields => [{:name => "a","type"=>"t",:mode=>"n"},{:name => "c","type"=>"t",:mode=>"n"}], :name => "p",:t=>"r"},{:name => "q", :t => "s", :m => "n"}]}

    h1[:fields].mergeFields(h2[:fields])

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