Ruby:合并嵌套哈希

use*_*862 48 ruby hash merge nested

我想合并一个嵌套的哈希.

a = {:book=>
    [{:title=>"Hamlet",
      :author=>"William Shakespeare"
      }]}

b = {:book=>
    [{:title=>"Pride and Prejudice",
      :author=>"Jane Austen"
      }]}
Run Code Online (Sandbox Code Playgroud)

我想合并是:

{:book=>
   [{:title=>"Hamlet",
      :author=>"William Shakespeare"},
    {:title=>"Pride and Prejudice",
      :author=>"Jane Austen"}]}
Run Code Online (Sandbox Code Playgroud)

实现这个目标的巢方法是什么?

xle*_*ras 52

对于轨道3.0.0+或更高版本存在deep_merge的功能的ActiveSupport那不正是你问什么.

  • 这不起作用.它将用新数组替换现有数组.http://apidock.com/rails/v3.2.13/Hash/deep_merge它似乎适用于Rails 4:http://apidock.com/rails/v4.0.2/Hash/deep_merge (9认同)
  • 但是,问题不在于Rails,是吗?因此,这个答案是最受欢迎的答案,这有点令人恼火. (3认同)

Jon*_*n M 46

我在这里找到了一个更通用的深度合并算法,并像这样使用它:

class ::Hash
    def deep_merge(second)
        merger = proc { |key, v1, v2| Hash === v1 && Hash === v2 ? v1.merge(v2, &merger) : v2 }
        self.merge(second, &merger)
    end
end

a.deep_merge(b)
Run Code Online (Sandbox Code Playgroud)


小智 35

要添加到Jon M和koendc的答案中,下面的代码将处理哈希的合并,并且:如上所述nil,但它也将联合两个哈希中存在的任何数组(使用相同的键):

class ::Hash
    def deep_merge(second)
        merger = proc { |key, v1, v2| Hash === v1 && Hash === v2 ? v1.merge(v2, &merger) : Array === v1 && Array === v2 ? v1 | v2 : [:undefined, nil, :nil].include?(v2) ? v1 : v2 }
        self.merge(second.to_h, &merger)
    end
end

a.deep_merge(b)
Run Code Online (Sandbox Code Playgroud)


Rus*_*ell 10

出于各种原因 - 这只有在你想以相同的方式合并散列中的所有键时才会起作用 - 你可以这样做:

a.merge(b) { |k, x, y| x + y }
Run Code Online (Sandbox Code Playgroud)

当你传递一个块Hash#merge,k是要合并的关键,其中关键在两个存在ab,x是价值a[k]y为价值b[k].块的结果成为key的合并散列中的值k.

我想在你的具体情况下,nkm的答案会更好.


Ste*_*ley 6

回答你的问题有点晚了,但我写了一篇相当丰富的深度合并实用程序,现在由Daniel Deleo在Github上维护:https://github.com/danielsdeleo/deep_merge

它将根据您的需要精确合并您的数组.从文档中的第一个示例:

所以,如果你有两个像这样的哈希:

   source = {:x => [1,2,3], :y => 2}
   dest =   {:x => [4,5,'6'], :y => [7,8,9]}
   dest.deep_merge!(source)
   Results: {:x => [1,2,3,4,5,'6'], :y => 2}
Run Code Online (Sandbox Code Playgroud)

它不会合并:y(因为int和数组不被认为是可合并的) - 使用bang(!)语法会导致源覆盖.当不可合并的实体是时,使用非爆炸方法将保留dest的内部值找到.它将添加包含在x中的数组,因为它知道如何合并数组.它处理包含任何数据结构的哈希的任意深度合并.

关于Daniel的github repo的更多文档现在..


nkm*_*nkm -1

a[:book] = a[:book] + b[:book]
Run Code Online (Sandbox Code Playgroud)

或者

a[:book] <<  b[:book].first
Run Code Online (Sandbox Code Playgroud)