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

时间:2018-01-12 10:54:13

标签: ruby

为什么我不能将this.state.access合并到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})
  (repl):2:在nil:NilClass中的块中   (repl):2:update_inventory中   (repl):2:each中   (repl):5:update_inventory

1 个答案:

答案 0 :(得分:5)

由于older不包含来自newer的所有密钥,因此无法按预期工作。

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

  1. 在第一次迭代时,x:emeraldsy27,效果很好,因为older的值为:emeralds 1}}:

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

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

    导致错误的原因是Ruby尝试计算nil + 5nil没有+方法(因此“nil的未定义方法`+':NilClass” )。

  3. 要解决此问题,您可以添加检查密钥是否存在的条件。但是有一种更简单的方法: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}