使用inject将数组转换为哈希的问题

时间:2017-08-16 08:31:48

标签: ruby

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,否则会导致错误。

1 个答案:

答案 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

还有documentationinject的工作方式类似,但假设您要在块中改变同一个对象。因此,它不需要您在块的末尾返回它:(请注意,参数顺序是相反的)

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"}