【问题标题】:Merge values in a Hash合并哈希中的值
【发布时间】:2012-09-28 02:44:32
【问题描述】:
nodes = {
  :node1 => { 
    :inherits => nil, 
    :variables => { :foo => 1, :bar => 2 } 
  },
  :node2 => { 
    :inherits => :node1, 
    :variables => { :foo => 9, :baz => 4 } 
  }
}

我一直在尝试了解如何返回一个新的节点哈希,其中每个节点的 :variables 哈希与 :inheritance 中指定的节点的 :variables 合并。换句话说,node1 将保持原样,而 node2 以 :variabes => { :foo => 9, :bar => 2, :baz => 4 }

结尾

我一直在浏览涉及 Enumerable#inject、带有块的 Hash#merge 等的文档,并认为是时候寻求帮助了。

更新:

我想我会提供更新。这段代码当然不是解决方案,但它可能正朝着正确的方向前进......

nodes = {
  :node1 => { :inherits => nil, :variables => { :foo => 1, :bar => 2 } },
  :node2 => { :inherits => :node1, :variables => { :foo => 9, :baz => 4 } }
}

new = nodes.inject({}) do |result, (k, v)|
  result.merge k => v.merge({ :variables => { :a => 6, :b => 7 } })
end

返回

{:node2=>{:inherits=>:node1, :variables=>{:a=>6, :b=>7}}, :node1=>{:inherits=>nil, :variables=>{:a=>6, :b=>7}}}

所以 v.merge 没有按预期工作......

【问题讨论】:

    标签: ruby hash merge inject


    【解决方案1】:

    你想要Hash#merge:

    merged_variables = nodes[:node1][:variables].merge(nodes[:node2][:variables])
    

    【讨论】:

    • 这不会产生一个 :foo = 1 的节点吗?
    • 不,不会:{:foo=>9, :bar=>2, :baz=>4}
    • 谢谢。这可能有点过于具体,因为我试图返回一个新的节点哈希,每个节点的 :variables 根据需要合并(根据继承)。我将更新我的原始问题以反映这一点。
    【解决方案2】:
    nodes[:node2][:variables].replace(
      nodes[:node1][:variables]
      .merge(nodes[:node2][:variables])
    )
    

    【讨论】:

      【解决方案3】:
      merged_nodes = {}
      
      nodes.each do |name, node|
        merged_nodes[name] = node.dup
        merged_nodes[name][:variables] = if node[:inherits]
          nodes[node[:inherits]][:variables].merge node[:variables]
        else
          node[:variables].dup
        end
      end
      

      会给你

      {
        :node1=>{:inherits=>nil, :variables=>{:foo=>1, :bar=>2}},
        :node2=>{:inherits=>:node1, :variables=>{:foo=>9, :bar=>2, :baz=>4}}
      }
      

      但它不能处理更深层次的嵌套,即如果 :node3 继承 :node2...

      【讨论】:

      • 继续深入研究并得出以下结论:new = nodes.inject({}) do |result, (name, node)| vars = node[:inherits].nil? ? node[:variables] : nodes[node[:inherits]][:variables] result.merge name => node.merge(:variables => node[:variables].merge(vars)) end
      【解决方案4】:

      通过原地合并缩短一点:

      nodes[:node2][:variables].merge!(nodes[:node1][:variables])
      
      nodes #=> {:node1=>{:inherits=>nil, :variables=>{:foo=>1, :bar=>2}},
            #    :node2=>{:inherits=>:node1, :variables=>{:foo=>1, :baz=>4, :bar=>2}}}
      

      【讨论】:

        【解决方案5】:
        new = {}
        nodes.each do |e, v|
            v.each do |attribute, value|
                if attribute == :inherits
                    new[e] = value.nil? ? v : nodes[value][:variables].merge( v[:variables] )
                end
            end
        end
        
        p new  #=> {:node1=>{:inherits=>nil, :variables=>{:foo=>1, :bar=>2}}, :node2=>{:foo=>9, :bar=>2, :baz=>4}}
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2019-01-24
          • 1970-01-01
          • 2015-06-13
          • 1970-01-01
          • 2014-04-16
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多