hash deep_merge with arrays

时间:2014-01-19 22:36:03

标签: ruby hash merge

我搜索了有关使用deep_merge的所有答案;但是,我仍然遇到问题。我正在尝试合并2个哈希并为每个匹配添加一个特定的键。例如:

更新格式

哈希1:

{
  "actions"=> [
    {
      "causes"=> [
        {
          "shortDescription"=>"short description for run 1", 
          "userId"=>"user.a"
        }
      ]
    }
  ], 
  "artifacts"=> [], 
  "fullDisplayName"=>"Run #1", 
  "result"=>"FAILURE", 
  "changeSet"=> {
    "items"=>[], 
    "kind"=>nil
  }, 
  "culprits"=> []
}

哈希2:

{
  "actions"=> [
    {
      "causes"=> [
        {
          "shortDescription"=>"short description for run 2", 
          "userId"=>"user.b"
        }
      ]
    }
  ], 
  "artifacts"=> [], 
  "fullDisplayName"=>"Run #2", 
  "result"=>"FAILURE", 
  "changeSet"=> {
    "items"=>[], 
    "kind"=>nil
  }, 
  "culprits"=> []
}

密钥列表:

["key-one","key-two"]

我希望得到的哈希是:

{
  "actions"=> [
    {
      "causes"=> [
        { 
          "shortDescription"=> {
            "key-one" => "short description for run 1", 
            "key-two" => "short description for run 2"
          }, 
          "userId"=> {
            "key-one" => "user.a", 
            "key-two" => "user.b"
          }
        }
      ]
    }
  ], 
  "artifacts"=> {
    "key-one" => [], 
    "key-two" => []
  }, 
  "fullDisplayName"=> {
    "key-one" => "Run #1", 
    "key-two" => "Run #2"
  }, 
  "result"=> {
    "key-one" => "FAILURE", 
    "key-two" => "FAILURE"
  }, 
  "changeSet"=> {
    "items"=> {
      "key-one" => [], "key-two" => []
    }, 
    "kind"=> {
      "key-one" => nil, 
      "key-two" => nil
    }
  }, 
  "culprits"=> {
    "key-one" => [], 
    "key-two" => [] 
  }
}

1 个答案:

答案 0 :(得分:0)

如果h1h2是您希望合并的两个哈希值,并且h3是所需的结果,我认为以下内容应该有效:

@merge_key1, @merge_key2 = "key-one", "key-two"

def merge_em(g1, g2)
  case g1
  when Array
    g1.size.times {|i| merge_em(g1[i], g2[i])}
  when Hash
    g1.keys.each do |k|
      v = g1[k]
      if (Hash === v || (Array === v && !v.empty?)) 
        merge_em(v, g2[k])
      else
        g1[k] = {@merge_key1 => v, @merge_key2 => g2[k]}
      end
    end
  end
end

h = Marshal.load(Marshal.dump(h1))
merge_em(h, h2)
p (h == h3) # => true

一些注意事项:

  • 此解决方案取决于哈希结构;如果结构发生变化,它可能无效。
  • Marshal.load(Marshal.dump(h1))用于制作h1的“深层副本”,因此h1不会被修改。如果可以修改h1,则merge_em(h1, h2)就足够了,h1是合并的哈希值。
  • gem awesome_print为您提供了这些复杂结构的精美格式显示。您在此处需要做的就是require 'ap',然后是ap h。试试吧!