【问题标题】:hash.merge with block to add up sub-hash keys?hash.merge 与块相加子哈希键?
【发布时间】:2019-02-02 00:47:24
【问题描述】:

我已经阅读了一些关于哈希与块合并的内容,这对于普通 ruby​​ 中的简单、非嵌套哈希效果很好。以下代码按预期生成{1=>2, 2=>4, 4=>6}

a = {1 => 1, 2 => 2, 4 => 3}
b = {1 => 1, 2 => 2, 4 => 3}
a.merge(b) { |key, value_a, value_b | value_a + value_b }

但合并不适用于嵌套哈希结构,我得到一个 NoMethodError (undefined method '+' for {1=>1, 2=>2}:Hash)

a = { "2018" => {1 => 1, 2 => 2, 4 => 3} }
b = { "2019" => {1 => 1, 2 => 2, 4 => 3} }
c = a.merge(b) { |key, value_a, value_b | value_a + value_b }

我已阅读有关 each_with_object 的信息,但不确定如何使用它。有没有一种聪明的方法来完成子哈希值的合并?你认为最简单的方法是什么?

【问题讨论】:

  • 如果你在 Rails 上,试试a.deep_merge(b) { |key, value_a, value_b| value_a + value_b }
  • Ruby: merge nested hash的可能重复
  • 我使用的是纯红宝石 :(
  • 在第二种情况下a.merge(b) 的预期输出是什么,似乎没有什么可以合并的,因为两个键不重合。
  • Enumerable#each_with_object 只是节省了几个步骤。例如,如果您写了def doit(arr); a = []; arr.each { |n| a << 2*n if n.odd? }; a; end,则可以通过写def doit(arr); arr.each_with_object([]) { |n,a| a << 2*n if n.odd? }; end 来消除第一个和最后一个语句。

标签: ruby hash


【解决方案1】:

您可以使用来自积极支持的Hash#deep_merge 来执行此操作。

require 'active_support/all'

a = { k1: { k2: 1 } }
b = { k1: { k2: 2 } }

a.deep_merge(b) { |k, v1, v2| v1 + v2 }
# => { l1: { k2: 3 } }

【讨论】:

    【解决方案2】:

    嵌套Hash,嵌套Hash#merge

    我把b的key改成了"2018"

    a = { "2018" => {1 => 1, 2 => 2, 4 => 3} }
    b = { "2018" => {1 => 1, 2 => 2, 4 => 3} }
    c = a.merge(b) { |k, v1, v2| v1.merge(v2) { |kk, aa, bb | aa + bb } }
    
    #=> {"2018"=>{1=>2, 2=>4, 4=>6}}
    

    对于您的原始值:

    a = { "2018" => {1 => 1, 2 => 2, 4 => 3} }
    b = { "2019" => {1 => 1, 2 => 2, 4 => 3} }
    

    结果是

    #=> {"2018"=>{1=>1, 2=>2, 4=>3}, "2019"=>{1=>1, 2=>2, 4=>3}}
    

    【讨论】:

    • 很好的简单答案!
    • 好答案。读者:这使用Hash#merge 的形式,它使用一个块来确定在被合并的两个散列中存在的键的值。正如所见,这是在两个层面上完成的。如果c = { "2018" => {1 => 1, 2 => 2, 4 => 9} },使用Ruby v2.6(参见链接文档)可以写a.merge(b, c) { |k, v1, v2| v1.merge(v2) { |kk, aa, bb | aa + bb } } #=> {"2018"=>{1=>3, 2=>6, 4=>15}}
    猜你喜欢
    • 2011-05-27
    • 2019-05-03
    • 1970-01-01
    • 1970-01-01
    • 2015-08-16
    • 1970-01-01
    • 2013-03-29
    • 2021-05-14
    • 1970-01-01
    相关资源
    最近更新 更多