这是我尝试做的事情的本质,但是'打破'没有权利:
needle = nil
haystacks.each do |haystack|
needle = haystack.look_for_needle()
break if needle
end
这个更短,但它会遍历每个草堆(不看至少),即使它不需要:
needle = nil
haystacks.each do |haystack|
needle ||= haystack.look_for_needle()
end
这是一个单行,但(我相信)它不是懒惰的,所以它做了不必要的工作:
needle = hackstacks.map{|h| h.look_for_needle()}.detect{|x| !x.nil?}
我觉得应该有一个班轮,但我不确定会不会:
needle = hackstacks.some_find_each_first_detect_lazy_map_thingee {|h| h.look_for_needle()}
答案 0 :(得分:6)
使用Ruby 2.x lazy enumerators:
needle = haystacks.lazy.map(&:look_for_needle).reject(&:nil?).first
或者:
needle = haystacks.lazy.map(&:look_for_needle).detect { |needle| !needle.nil? }
或者:
needle = haystacks.lazy.map(&:look_for_needle).detect(&:itself)
答案 1 :(得分:2)
haystack.find &:itself
haystack.index &:itself
您更喜欢哪一个?
答案 2 :(得分:1)
我认为find_proverbial_needle_in_a_haystack
和look_for_needle
都会返回针头或nil
,后者如果没有大海捞针包含针头。
class Haystack
def initialize(haystack)
@haystack = haystack
end
# Suppose look_for_needle is defined as follows
def look_for_needle
@haystack.include?(:straw) && :straw
end
end
def find_proverbial_needle_in_a_haystack(haystacks)
needle = nil # can be anything
haystacks.find { |haystack| needle = haystack.look_for_needle } && needle
end
find
返回块评估true
的第一个干草堆,如果在任何干草堆中找不到针,则返回nil
。
haystacks = [Haystack.new([:ball, :top]),
Haystack.new([:fluff, :straw]),
Haystack.new([:dog, :cat])]
#=> [#<Haystack:0x007fdaaa0f6860 @haystack=[:ball, :top]>,
# #<Haystack:0x007fdaaa0f67e8 @haystack=[:fluff, :straw]>,
# #<Haystack:0x007fdaaa0f6590 @haystack=[:dog, :cat]>]
find_proverbial_needle_in_a_haystack(haystacks)
#=> :straw
haystacks = [Haystack.new([:ball, :top]),
Haystack.new([:fluff, :yellow_stuff]),
Haystack.new([:dog, :cat])]
#=> [#<Haystack:0x007fdaaa082f50 @haystack=[:ball, :top]>,
# #<Haystack:0x007fdaaa082f00 @haystack=[:fluff, :yellow_stuff]>,
# #<Haystack:0x007fdaaa082eb0 @haystack=[:dog, :cat]>]
find_proverbial_needle_in_a_haystack(haystacks)
#=> nil
答案 3 :(得分:1)
对于Ruby 2.0及更高版本,我使用此方法扩展了Enumerable:
module Enumerable
TRUTHY_LAMBDA = lambda {|result| !!result }
def first_result(detect_result_lambda=TRUTHY_LAMBDA, &block)
self.lazy.collect(&block).detect {|result| detect_result_lambda.call(result) }
end
end
因此您可以致电:
haystacks.first_result {|haystack| haystack.find_needle() }
..它将返回针。
如果需要确保它是was缝针,可以执行以下操作:
haystacks.first_result(lambda {|needle| needle&.for_quilting? }) {|haystack| haystack.find_needle() }
或使用do块格式化的相同代码:
haystacks.first_result(lambda {|needle| needle&.for_quilting? }) do |haystack|
haystack.find_needle()
end
P.S。 -如果有人可以告诉我如何改进此代码以支持以下语法,那将是惊人的(我收到错误消息“ SyntaxError:同时给出了块arg和实际块”,这向我暗示了Ruby正在分配“&:for_quilting? “到&block而不是第一个参数)
haystacks.first_result(&:for_quilting?) {|haystack| haystack.find_needle() }
答案 4 :(得分:0)
有一种first
方法正是如此。
它需要一个块并返回块的第一个匹配
match = haystacks.first { |x| x.find_needle }
https://ruby-doc.org/core-2.2.0/Array.html#method-i-first
顺便说一句,您可以使用each
或map
而无需更多按键:
match = haystacks.each { |x| break x if x.find_needle }
match = haystacks.map { |x| break x if x.find_needle }
虽然没有真正使用each
或map
的正确语义,您希望返回一个数组(each
返回原始数组并map
返回一个转换后的数组)