将逻辑与运算应用于布尔值列表

27
在Scala中考虑以下布尔值列表。
List(true, false, false, true)

你如何使用foldRight或foldLeft来模拟对列表中所有值执行逻辑AND函数的功能?


也许一个关于折叠的通用教程会有所帮助:https://dev59.com/fHE95IYBdhLWcg3wft1w - Rex Kerr
5个回答

65

除了使用 foldLeft/Right,你也可以使用 forall(identity) 来表示逻辑与,或者使用 exists(identity) 来表示逻辑或。

编辑:这些函数的好处在于可以提前退出。如果 forall 遇到 false 或者 exists 遇到 true,它们会立即返回。


1
小心退化情况,这可能会违反直觉。基本上,以下两个表达式都是 true: List.empty[Boolean].forall(identity) == trueList.empty[Boolean].exists(identity) == false - Randall Schulz
1
真的,但是使用 &&|| 进行折叠会得到相同的结果。 - drexin
6
这些行为是非常合乎逻辑的。假设有一个谓词p和一个空值集合S = {},那么对于语句“对于S中的所有x,p(x)成立”,它显然是正确的;而对于语句“存在一个x在S中使得p(x)成立”,无论p的定义如何,都是错误的。 - yonil

16
val l = List(true, false, false, true)
val andAll = l.foldLeft(true)(_ && _)

reduceOption可以帮助处理退化情况(请参见下面的答案)。 - sfosdal

9

foldLeft没有初始值。

List(true, false, false, true).reduce(_&&_)

然而,这对于List.empty[Boolean]不起作用。


5

只要符合你的使用情况,我最喜欢的方法是使用forAll。它能够提前退出,非常方便。但是如果这个方法不适用,还有另一种稍微复杂一些的方法。

使用reduceOption方法,你不能提前退出,但是你可以清楚地指定列表为空时的返回值。

val l = List(true, false, false, true)
val andAll = l.reduceOption(_ && _).getOrElse(false)

0

OP明确要求使用foldRightfoldLeft来解决问题,所以被接受的答案是严格正确的。当前得票最多的答案-使用forall-由于具有提前退出的优势而具有更好的性能。这里有另一种解决方案-使用contains-同样具有提前退出,并且可能更易读。

对于逻辑与:

!List(true, false, false, true).contains(false)

对于逻辑 OR,它甚至更简单,不需要否定:

List(true, false, false, true).contains(true)

关于“退化”的空列表情况,使用逻辑与的注意事项:
!List.empty[Boolean].contains(false)
// Returns true

如果那不符合你的使用情况,有一个略微复杂的解决方案:
Some(List.empty[Boolean]).filter(_.nonEmpty).exists(!_.contains(false))
// Returns false

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接