Ruby – Array.find,但返回块的值
我有一个数组,我想要第一个块的结果返回一个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
有任何想法吗?
[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
break
是丑陋的= P
如果你想要一个function方法,你想要一个懒惰的地图:
[nil, 1, 2, 3].lazy.map{|i| i && i.to_s}.find &:itself # => "1"
如果你不相信它不是在整个arrays中迭代,只需打印出来并看到:
[nil, 1, 2, 3].lazy.map{|i| (pi) && i.to_s}.find &:itself # nil # 1 # => "1"
用块替换i.to_s
。
这是你想要做的吗?
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
find_yield
做你想要的,查看带有许多核心扩展的ruby facets,特别是find_yield
Enumberable方法: https : //github.com/rubyworks/facets/blob/master/lib/core/facets/enumerable/find_yield.rb
这是我的看法,这是否更接近您的实际用例? 注意b
的内容是3
而不是2
因为在b
上也调用了my_test_with_side_effect
。
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 } => # a => # b => # c => #
我怀疑有办法做到这一点。 问题是Ruby在块中创建了一个闭包,而变量i
在它本地。 执行i+=1
可以扩展到i = i + 1
,这会在块的范围内创建一个新的变量i
,并且不会修改任何a,b,c
变量中的值。