无法使用 .each to 进行哈希值操作

  • 本文关键字:哈希值 操作 to each ruby
  • 更新时间 :
  • 英文 :


为什么我不能将newer组合到older

def update_inventory(older, newer)
  newer.each {|x, y| older[x] += y}
end
update_inventory({rubies: 10, emeralds: 14, diamonds: 2}, {emeralds: 27, moonstones: 5})

未定义方法 +' 表示nil:NilClass
(重复(:2:在update_inventory
块中 (重复(:2:在each
(重复(:2:在update_inventory
(重复(:5:<main>

它无法按预期工作,因为older不包含newer中的所有键。

newer由两个键值对组成: {emeralds: 27, moonstones: 5} 因此newer.each将调用块{ |x, y| ... }两次:

  1. 在第一次迭代中,x :emeraldsy 27工作正常,因为它具有 :emeralds 的值older

    older[:emeralds]       #=> 14
    older[:emeralds] += 27 #=> 41
    
  2. 在第二次迭代中,x :moonstonesy 5 ,因此得到:

    older[:moonstones]      #=> nil
    older[:moonstones] += 5 #=> NoMethodError: undefined method `+' for nil:NilClass
    

    该错误是由于 Ruby 尝试计算nil + 5nil 没有+方法(因此"nil:NilClass 的未定义方法'+'"(。


若要解决此问题,可以添加一个条件来检查密钥是否存在。但是有一个更简单的方法:Hash#update完全符合您的需求:

def update_inventory(older, newer)
  older.update(newer) { |_, v1, v2| v1 + v2 }
end

它会将键值对从newer复制到older。如果两个哈希中都存在一个键,则将调用该块来确定新值。

older = {rubies: 10, emeralds: 14, diamonds: 2}
newer = {emeralds: 27, moonstones: 5})
older.update(newer) { |_, v1, v2| v1 + v2 }
#=> {:rubies=>10, :emeralds=>41, :diamonds=>2, :moonstones=>5}

最新更新