Ruby Enumerable:得到第一个不是nil,但结果必须是块里面的内容

时间:2016-01-07 13:35:42

标签: ruby enumerable

Enumerable#find方法通过评估直到找到与块中的条件匹配的元素为止。第一次将块评估为nil时是否有类似的返回值?想象一个人会有一组哈希:

value = nil
options.each do |o|                     
  break if value = o[:desired]
end                                     
value ||= DEFAULT

有没有一种方法可以实现这个目标?

对集合进行大量转换毫无意义,我希望尽量减少分配数量,因此任何分配新数组的解决方案对我都不利。

5 个答案:

答案 0 :(得分:2)

find方法可用于查找具有最小迭代次数:desired的第一个元素。

我认为您希望从块中获取desired键的值而不是元素本身 - Enumerable中没有任何方法表现得像find和{{的混合1}} - 你必须使用在块内分配值的外部变量,如下所示。

map

它或多或少看起来像你的代码,它应该也可以正常工作。

如果您想使用options = [{foo: 1}, {desired: 2}, {bar: 3}] value = nil options.find do |o| value = o[:desired] break if value end p value #=> 2 方法,下面是一种可以使用的方法,但它会迭代所有元素。

Enumerable

答案 1 :(得分:0)

您可以使用reduce

value = options.reduce(nil){|memo, entry|  memo || entry[:desired]  } || DEFAULT

答案 2 :(得分:0)

从Ruby 2.0开始,这可以通过将#map#findlazy enumerables组合在一起来实现:

value = options.lazy.map { |o| o[:desired] }.find { |x| !x.nil? } # or find(&:present?) with ActiveSupport
value ||= DEFAULT

答案 3 :(得分:0)

今天这对我来说很重要:我认为我们可以使用带有reduce值的break

treasure = [1,2,3].reduce(nil) do |memo, value|
  break memo if memo
  foo(value)
end

答案 4 :(得分:0)

怎么样

options.reduce{ |_,o|
   break o if o[:desired]
   DEFAULT
}

catch do |tag|
   options.each{ |_,o| o[:desired] and throw tag, o }
   DEFAULT
end

后者允许递归。