来自Hash.each和Hash.inject实现的不同结果

时间:2015-08-29 15:04:01

标签: ruby each inject

我试图理解为什么我从两个表达中得到不同的结果,我认为它们在功能上完全相同。

each方法:

matches = {}
@entries.each do|entry, definition|
    matches.merge!({entry => definition}) if entry.match(/^#{entry_to_find}/)
end
matches

inject方法:

@entries.inject({}) {|matches, (entry, definition)| matches.merge!
({entry => definition}) if entry.match(/^#{entry_to_find}/)}

each代码块在运行时给出正确的答案,但inject一直返回nil,我不明白为什么。我希望使用inject,因为它是一段更短的代码。

2 个答案:

答案 0 :(得分:3)

这是因为如果条件不满足,if将返回nil,并且将在下一次迭代中用于matches的值。请改用Enumerable#each_with_object

@entries.each_with_object({}) do |(entry, definition), matches| 
  matches.merge!({entry => definition}) if entry.match(/^#{entry_to_find}/)
end

答案 1 :(得分:2)

我认为ndn's analysis of why your inject approach doesn't work是正确的。至于更短的替代方案,因为您希望那些满足您条件的未修改的键值对@entries,您是否考虑过Hash#select

matches = @entries.select { |entry, definition| entry.match(/^#{entry_to_find}/) }