Ruby - Array.find,但返回块的值

时间:2014-07-23 02:03:11

标签: ruby

我有一个数组,我想要第一个块的结果返回一个truthy值(又名,不是nil)。问题在于,在我的实际使用案例中,测试有副作用(我实际上迭代了一组队列,然后弹出顶部),所以我不需要评估块以外的第一次成功。

a,b,c = [1,2,3]

[a,b,c].first_but_value{ |i| (i + 1) == 2 } == 2

a == 2
b == 2
c == 3

有什么想法吗?

6 个答案:

答案 0 :(得分:12)

break丑陋= P

如果你想要一种功能性方法,你需要一个懒惰的地图:

[nil, 1, 2, 3].lazy.map{|i| i && i.to_s}.find &:itself   
# => "1"

如果您不相信它不会在整个阵列中进行迭代,只需打印出来并查看:

[nil, 1, 2, 3].lazy.map{|i| (p i) && i.to_s}.find  &:itself
# nil
# 1
# => "1"

i.to_s替换为您的阻止。

答案 1 :(得分:9)

[1, 2, 3].detect { |i| i += 1; break i if i == 2 } 
# => 2

[1, 2, 3].detect { |i| i += 1; break i if i == 10 }
# => nil

答案 2 :(得分:3)

这是你想要做的吗?

a, b, c = 1, 2, 3

binding.tap { |b|
  break b.local_variable_get [ :a, :b, :c ].find { |sym|
    b.local_variable_set( sym, b.local_variable_get( sym ) + 1 ) == 2
  }
} #=> 2

a #=> 2
b #=> 2
c #=> 3

答案 3 :(得分:3)

find_yield执行您想要的操作,查看包含许多核心扩展的ruby方面,尤其是find_yield Enumberable方法:https://github.com/rubyworks/facets/blob/master/lib/core/facets/enumerable/find_yield.rb

答案 4 :(得分:2)

这是我的看法,这是否更接近您的实际用例?请注意,b的内容为3而不是2,因为my_test_with_side_effect上也会调用b

class MyQueue
  def initialize(j)
    @j = j
  end  
  def my_test_with_side_effect
    (@j+=1) == 2
  end
end

(a,b,c) = [MyQueue.new(1),MyQueue.new(2),MyQueue.new(3)]
[a,b,c].each { |i| break i unless i.my_test_with_side_effect }
=> #<MyQueue:0x007f3a8c693598 @j=3>
a
=> #<MyQueue:0x007f3a8c693980 @j=2>
b
=> #<MyQueue:0x007f3a8c693598 @i=3>
c
=> #<MyQueue:0x007f3a8c693430 @i=3>

答案 5 :(得分:0)

我怀疑是否有办法做到这一点。问题是Ruby在块中创建了一个闭包,变量i是本地的。可以将i+=1扩展为i = i + 1,这会在块的范围内创建新变量i,并且不会修改任何a,b,c中的值变量。