假设我有一个值数组[a,b,c,d,...]和一个返回true或false的函数f(x,...)。
[1,2,3,4].map {|x| f(x)} => [true true false true]
首先,将结果列表折叠为真值或假值(通过AND)的最佳方法是什么?是否有一个允许我映射的函数:
[true true false true]
为:
((true && true) && false) && true
使用二进制&&的累积成对应用。操作
在这种情况下,评估函数的成本是次要的,因此希望使用lisp样式的“和”来顺序评估参数(函数应用程序),直到其中一个为假。确定可以这样做:
!![1,2,3,4].each {|x| break false if !f(x) }
哪个很难看。希望有更优雅的方式来做到这一点。我知道我可以为Array添加一个新的理解,但希望有一些内置的东西可以做得更好。感谢
答案 0 :(得分:12)
您正在寻找Enumerable#all?
,如果其块的所有调用都是真实的,则返回true。还有Enumerable#any?
,如果其块的任何调用都是真实的,则返回true:
#!/usr/bin/ruby1.8
def even(n)
n % 2 == 0
end
p [1, 2, 3, 4].all? { |i| even(i) } # => false
p [2, 4, 6, 8].all? { |i| even(i) } # => true
p [1, 2, 3, 4].any? { |i| even(i) } # => true
p [1, 3, 5, 7].any? { |i| even(i) } # => false
any?
short-curcuits:第一个truthy值导致它返回true。 all?
短路也是如此:第一个假值导致它返回false。
答案 1 :(得分:3)
您可以尝试折叠阵列:
[true,true,false,true].inject(:&) #=> false (AND-ed)
[true,true,false,true].inject(:|) #=> true (OR-ed)
[1,2,3,4].inject(:+) #=> 10 (summed)
[1,2,3,4].inject(:*) #=> 24 (multiplied)
你得到了线索。回到你的例子:
[1,2,3,4].map {|x| f(x) }.inject(:&)
然而它不会短路 - 你可能最好看看“任何?”还是“全部?”除了你的“f()”有副作用(比如修改持久存储)。
答案 2 :(得分:1)
如何:[true, true, false, true].all?
如果数组不包含任何计算结果为false或nil的内容,则返回true。