data_arr = [['dog', 'Fido'], ['cat', 'Whiskers'], ['fish', 'Fluffy']]
data_hash = data_arr.inject({}) do |hsh, v|
hsh[v[0]] = v[1]
hsh
end
嗨,为什么我不需要将data_hash初始化为空哈希?为什么我必须在最后一行添加hsh,否则会导致错误。
答案 0 :(得分:3)
为什么我不需要将
data_hash
初始化为空哈希?
你这是暗示的。传递给inject
的值,即{}
将成为hsh
的初始值,最终将成为data_hash
的值。根据{{3}}:
在迭代结束时, memo 的最终值是该方法的返回值。
让我们看看如果我们没有通过{}
会发生什么:
如果您没有为备忘录明确指定初始值,那么集合的第一个元素将用作备忘录的初始值
集合的第一个元素是数组['dog', 'Fido']
。如果省略{}
,则inject
会将该数组用作hsh
的初始值。随后对hsh[v[0]] = v[1]
的调用将失败,原因是:
hsh = ['dog', 'Fido']
hsh['cat'] = 'Whiskers'
#=> TypeError: no implicit conversion of String into Integer
为什么我必须在最后一行添加hsh
再次,让我们查看文档:
[...] [指定块的]结果成为备忘录的新值。
inject
希望您在块的末尾返回hsh
的新值。
如果不是,则会导致错误。
这是因为像hsh[v[0]] = v[1]
之类的作业会返回指定的值,例如'Fido'
。因此,如果省略最后一行,'Fido'
将成为hsh
的新值:
hsh = 'Fido'
hsh['cat'] = 'Whiskers'
#=> IndexError: string not matched
还有documentation与inject
的工作方式类似,但假设您要在块中改变同一个对象。因此,它不需要您在块的末尾返回它:(请注意,参数顺序是相反的)
data_hash = data_arr.each_with_object({}) do |v, hsh|
hsh[v[0]] = v[1]
end
#=> {"dog"=>"Fido", "cat"=>"Whiskers", "fish"=>"Fluffy"}
或使用each_with_object
:
data_hash = data_arr.each_with_object({}) do |(k, v), hsh|
hsh[k] = v
end
#=> {"dog"=>"Fido", "cat"=>"Whiskers", "fish"=>"Fluffy"}
虽然要将数组转换为哈希,但只需使用array decomposition即
[...]将 ary 解释为
[key, value]
对的数组
data_arr.to_h
#=> {"dog"=>"Fido", "cat"=>"Whiskers", "fish"=>"Fluffy"}