当不是nil时,在Enumeration上返回块的值

时间:2011-11-09 21:11:57

标签: ruby enumerable

我似乎对Ruby Enumerable有一个奇怪的用例。我试图做以下事情:

result = my_strategies.some_method do |strategy|
    strategy.get_result
end

方法 some_method 只是一个占位符,但却是此问题其余部分的基础。

可枚举的my_strategies包含从远程服务检索值的有序策略列表;更优选的策略是在不太优选的策略之前运行,

有时候更优选的策略会失败,因为单独重试不会纠正。在这种情况下,策略将返回nil。

我可以通过依赖每个块看到一种方法:

result = nil

my_strategies.each do |strategy|
    result = strategy.get_result
    if not r.nil?
        break
    end
end

这似乎不必要地吵闹。我想知道在我的第一个例子中是否有一种方法可以替代 some_method ;类似于.any?的东西,但返回导致块为真的值,而不是返回true。

我也欢迎对我想做的事情采取替代方法。

编辑:我最初问过这个问题,因为我尝试过这段代码:

result = my_strategies.find do |strategy|
    strategy.get_result
end

除了这使我成功的策略,而不是它返回时返回的值。我不关心哪种策略让我有价值,我只想知道价值是什么。

3 个答案:

答案 0 :(得分:7)

您的需求非常普遍,但不幸的是核心中没有这样的抽象。但是,Facets家伙很久以前发现了这一差距并实施了Enumerable#find_yield(a.k.a Enumerable#map_detect):

result = my_strategies.map_detect { |strategy| strategy.get_result }

或者简单地说:result = my_strategies.map_detect(&:get_result)。 Ruby 2.0实现了懒惰的枚举(对于早期版本使用enumerable-lazy)所以现在我们可以写:

result = my_strategies.lazy.map(&:get_result).reject(&:nil?).first

答案 1 :(得分:1)

您可以使用Enumerable#find遍历数组,直到获得结果:

result = nil

my_strategies.find do |strategy|
    result = strategy.get_result
end

答案 2 :(得分:0)

另一种方法(不使用块):

result = nil
num = 0

while result.nil?
  result = my_strategies[num].get_result
  num += 1
end