列表中AND的最佳功能方法

时间:2010-03-01 13:49:08

标签: ruby

假设我有一个值数组[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添加一个新的理解,但希望有一些内置的东西可以做得更好。感谢

3 个答案:

答案 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。