如何在Ruby中深度合并两个嵌套的数组哈希?

时间:2014-02-05 17:51:58

标签: ruby arrays hash merge

我试图合并两个嵌套的哈希数组数组。

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

这是我期待的输出。

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

我使用过deep_merge& deep_merge!然而,这并没有给我预期的结果。感谢任何指针。

谢谢, NAVNEET

2 个答案:

答案 0 :(得分:0)

如评论中所述,对于您想要的内容,将没有通用解决方案。下面的代码应该适用于您的嵌套结构(并且非常难看):

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

问题是 - 你为什么需要这样做?很可能有更好的方法来做你想要实现的目标。

答案 1 :(得分:0)

以下是我写的解决方法:

    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])