我有一个数组,我想要第一个块的结果返回一个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
有什么想法吗?
答案 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
中的值变量。