Ruby idiom to shortcircuit使用each和map返回第一个非nil

Ric*_*ick 6 ruby each

这是我想要做的事情的本质,但"休息"不能正确地进行:

needle = nil
haystacks.each do |haystack|
  needle = haystack.look_for_needle()
  break if needle
end
Run Code Online (Sandbox Code Playgroud)

这个更短,但它会迭代每个干草堆(至少看不到),即使它不需要:

needle = nil
haystacks.each do |haystack|
  needle ||= haystack.look_for_needle()
end
Run Code Online (Sandbox Code Playgroud)

这是一个单行,但(我相信)它不是懒惰,所以它做了不必要的工作:

needle = hackstacks.map{|h| h.look_for_needle()}.detect{|x| !x.nil?}
Run Code Online (Sandbox Code Playgroud)

我觉得应该有一个班轮,但我不确定它会是:

needle = hackstacks.some_find_each_first_detect_lazy_map_thingee {|h| h.look_for_needle()}
Run Code Online (Sandbox Code Playgroud)

tok*_*and 7

使用Ruby 2.x 懒惰枚举器:

needle = haystacks.lazy.map(&:look_for_needle).reject(&:nil?).first
Run Code Online (Sandbox Code Playgroud)

要么:

needle = haystacks.lazy.map(&:look_for_needle).detect { |needle| !needle.nil? }
Run Code Online (Sandbox Code Playgroud)

要么:

needle = haystacks.lazy.map(&:look_for_needle).detect(&:itself)
Run Code Online (Sandbox Code Playgroud)

  • 从 2.7 开始,您可以使用 [`filter_map`](https://ruby-doc.org/core-2.7.0/Enumerable.html#method-i-filter_map) 跳过`检测/拒绝`步骤:`haystacks .lazy.filter_map(&:look_for_needle).first` (2认同)

Bor*_*cky 1

haystack.find &:itself
haystack.index &:itself
Run Code Online (Sandbox Code Playgroud)

你更倾向哪个?