Ruby inject从数组生成哈希遇undefined method `[]=' for nil:NilClass报错
报错根因
inject(别名reduce)的核心运行规则是:代码块内最后一行表达式的返回值,会自动作为下一次迭代的累积参数(也就是你块里定义的hash变量),同时也是整个inject方法执行完成后的最终返回值。
你当前的代码块内,最后执行的语句是puts hash,而Ruby中puts方法的固定返回值是nil:
- 第一轮迭代时,初始累积值是你传的空哈希
{},你给这个哈希完成键值赋值后,执行puts hash打印内容,块的返回值是nil - 第二轮迭代时,inject会把上一轮块的返回值
nil当成新的累积值传给块,此时你对着nil调用[]=赋值方法,就直接抛出了undefined method[]=' for nil:NilClass`错误。
修正方式
只需要在代码块的最后,显式将修改完成的哈希作为返回值返回,不要让puts这类返回值为nil的语句成为块的最后一行即可。
修正后的可正常运行代码:
def int_hash() [[:key1, "value1"], [:key2, "value2"]].inject({}) do |hash, element| hash[element.first] = element.last puts hash hash # 显式返回哈希,作为下一轮迭代的累积值 end end int_hash()
常见踩坑补充
- 很多教程示例里没写显式返回的代码也能正常运行,是因为示例里代码块的最后一行就是赋值操作
hash[element.first] = element.last——赋值表达式在Ruby中的返回值就是被写入的哈希本身,会自动传给下一轮迭代,不会出现值丢失的问题。 - 如果只是想从二维键值数组生成哈希,不需要写inject逻辑,直接调用数组的
to_h方法就能一步实现,但如果是练习inject的累积逻辑,只要记住块的返回值传递规则,就不会踩这类坑。
内容的提问来源于stack exchange,提问作者Jack
相关产品推荐
相关产品推荐

