# How to map a function with boolean operators over an array?

I am a beginner in Mathematica. I have this in Mathematica v12:

A = {1, 1, 1, 1}
B = {2, 2, 2, 2}
A+B
(* 3,3,3,3 *)


I'd like to experiment with evaluating arbitrary expressions on arrays, like this:

C = {4, 2, 4, 2}
(A+B)<C
(* I want this output: *)
(* True, False, True, False *)


In the example, above:

• {1,1,1,1} + {2,2,2,2} evaluates to {3,3,3,3} which is an element-wise operation.
• {3,3,3,3} < {4,2,4,2} should evaluate to { True, False, True, False }, but it does not do an element-wise operation (which seems logically inconsistent!).

### What I have tried

Tried about 30 combinations and permutations of existing functions, none of them appeared to work. Tried the top 6 answers that were vaguely relevant on SO. Browsed through Mathematica documentation to try and find anything relevant.

• In haskell: zipWith (<) (zipWith (+) [1,1,1,1] [2,2,2,2]) [4,2,4,2] Mar 19, 2021 at 10:43
• In python: [x+y<z for x,y,z in zip([1,1,1,1],[2,2,2,2],[4,2,4,2])] Mar 19, 2021 at 18:26

Update

Can generalize this to account for scalars using ReplaceRepeated and some pattern matching.

bolVectorEval[exp_] :=
exp //. h_[params : OrderlessPatternSequence[_List .., _?NumericQ ...]] :>


then

bolVectorEval[(a > c) || (4.3 < (b + c))]

{True, False, True, False}


OP

You may use Thread.

Thread[(a + b) < c]

{True, False, True, False}


Hope this helps.

• Thanks! The first answer works perfectly to evaluate expressions with logical operators such as || or &&, e.g. bolVectorEval[((a + b) > (c + a)) || (a > c)]. @Henrik Schumacher also recommended BoolEval by Szabolcz, that works perfectly as well, and claims to be optimised for efficiency. Example: BoolEval[((a + b) > (c + a)) || (a > c)]. Mar 18, 2021 at 13:43

You may exploit that UnitStep step is vectorized like this:

a = {1, 1, 1, 1};
b = {2, 2, 2, 2};
c = {4, 2, 4, 2};
{False, True}[[2 - UnitStep[(a + b) - c]]]


{True, False, True, False}

If you can life with 0 and 1 instead of False and True, the the following will serve your needs and is more efficient (for large lists):

Subtract[1, UnitStep[Subtract[(a + b), c]]]


In particular, it is two orders of magnitude faster than Thread:

n = 1000000;
a = RandomInteger[{0, 1000}, {n}];
b = RandomInteger[{0, 1000}, {n}];
c = RandomInteger[{0, 1000}, {n}];

r1 = Thread[(a + b) < c]; // RepeatedTiming // First
r2 = Subtract[1, UnitStep[Subtract[(a + b), c]]]; // RepeatedTiming // First
And @@ ({False, True}[[r2 + 1]] == r1)


0.34

0.0025

True

But of course, Thread is more convenient and also more readible.

Szabolcs wrote a nice packaged that gives you the best of both worlds: It's called BoolEval.

• Thank you for your answer. I'm after a more general solver, i.e. I could plug in (a+b)>c or even ((a+b)>(c+d)) || (a>d), and it would do an element-wise apply of that function to get something like { True, False, True, False } Mar 18, 2021 at 12:41
• Unitize[UnitStep[(a + b) - (c + d)] + UnitStep[a - d]] ;) But I see your point. Szabolcz wrote a nice packaged with the name BoolEval. Have a look! Mar 18, 2021 at 12:44
• BoolEval works brilliantly, thanks! Mar 18, 2021 at 13:33
• Thank you for your answer. I've marked the answer by @Edmund as the one that worked for me. Mar 18, 2021 at 13:41
• You're welcome. Mar 18, 2021 at 13:42
vecLess = Negative @* Subtract;

vecLess[a + b, c]

{True, False, True, False}

a + b < c /. Less -> vecLess

{True, False, True, False}


Here's a very idiosyncratic way of handling the problem. This would be my goto method if I just needed to get things done and didn't care about performance. It's not the easiest to read, but there's a lot going on that someone new to MMA can learn from:

a = {1, 1, 1, 1};
b = {2, 2, 2, 2};
c = {4, 2, 4, 2};
#1+#2<#3&@@@Transpose[{a,b,c}]


{True, False, True, False}

This post is a great place to start if you're just getting into Mathematica.

• Thank you, and that post you referenced is amazing. Mar 18, 2021 at 13:49