Applying logical and to list of boolean values
Asked Answered
S

5

27

Consider the following list of Boolean values in Scala

List(true, false, false, true)

How would you using either foldRight or foldLeft emulate the function of performing a logical AND on all of the values within the list?

Saleable answered 19/3, 2014 at 21:44 Comment(1)
Maybe a general tutorial on folds would help: stackoverflow.com/questions/2293592Oxidize
C
16
val l = List(true, false, false, true)
val andAll = l.foldLeft(true)(_ && _)
Conjure answered 19/3, 2014 at 21:50 Comment(1)
reduceOption helps deal with the degenerate case (see answer below)Douville
W
66

Instead of using foldLeft/Right, you can also use forall(identity) for the logical AND, or exists(identity) for the logical OR.

edit: The benefit of these functions is the early exit. If forall hits a false or exists a true, they will immediately return.

Wrote answered 19/3, 2014 at 21:54 Comment(3)
Becareful of the degenerate case. It can be counter-intuitive. Basically, both of the following expressions are true: List.empty[Boolean].forall(identity) == true and List.empty[Boolean].exists(identity) == false.Karen
True, but you would get the same results for folding with && or ||.Wrote
These behaviours are perfectly logical. Given a predicate p and an empty set of values S = {}, of course the statement "p(x) for all in x in S" is true, and likewise "there exists x in S such that p(x)" is false, regardless of the definition of p.Rhinestone
C
16
val l = List(true, false, false, true)
val andAll = l.foldLeft(true)(_ && _)
Conjure answered 19/3, 2014 at 21:50 Comment(1)
reduceOption helps deal with the degenerate case (see answer below)Douville
D
9

Without initial value as in foldLeft,

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

Yet this works not for List.empty[Boolean].

Danieledaniell answered 20/3, 2014 at 7:39 Comment(0)
D
5

I like the forAll approach best so long as it fits your use case. It exits early which is great. However, if that doesn't fit here's another, only marginally more complex, approach.

With reduceOption you get no early exit, but you can clearly specify the value for the case where the list is empty.

val l = List(true, false, false, true)
val andAll = l.reduceOption(_ && _).getOrElse(false)
Douville answered 22/5, 2016 at 23:14 Comment(0)
K
0

The OP specifically asks for a solution using foldRight or foldLeft, so the accepted answer is strictly correct. The answer currently with most votes - using forall - has better performance due to early exit. Here's another solution - using contains - with early exit too and probably more readable.

For the logical AND:

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

For the logical OR it's even simpler, no negation is needed:

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

A note about the "degenerate" empty list case, with logical AND:

!List.empty[Boolean].contains(false)
// Returns true

If that doesn't fit your use case, a marginally more complex solution:

Some(List.empty[Boolean]).filter(_.nonEmpty).exists(!_.contains(false))
// Returns false
Kucera answered 12/12, 2022 at 20:6 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.