23
$\begingroup$

I'd like to take {True,True,False} and {True,False,False} and apply And to get {True,False,False}. Right now I'm using

And @@ # & /@ Transpose[{{True, True, False}, {True, False, False}}]

Is that really the best way? I would like And[{True, True, False}, {True, False, False}] to work but it does not.

$\endgroup$
2
  • 4
    $\begingroup$ +1 Nice question, invites many possible responses. $\endgroup$
    – DavidC
    Sep 4, 2012 at 16:51
  • $\begingroup$ Related: (3217) $\endgroup$
    – Mr.Wizard
    Jan 18, 2015 at 15:30

8 Answers 8

23
$\begingroup$

I like more :

MapThread[ And, {{True, True, False}, {True, False, False}}]
{True, False, False}

Edit

We should test efficiency of various methods for a few different lists.

Definitions

Argento[l_] := (And @@ # & /@ Transpose[l]; // AbsoluteTiming // First)
Brett[l_]   := (And @@@ Transpose[l]; // AbsoluteTiming // First)
Artes[l_]   := (MapThread[And, l]; // AbsoluteTiming // First)
kguler[l_]  := (And[l[[1]], l[[2]]] // Thread; // AbsoluteTiming // First)
RM[l_]      := (Inner[And, l[[1]], l[[2]], List]; // AbsoluteTiming // First)

Test I

l1 = RandomChoice[{True, False}, {2, 10^5}];
Argento[l1]
Brett[l1]
Artes[l1]
kguler[l1]
RM[l1]
0.2710000
0.0820000
0.0530000
0.0520000
0.0390000

Test II

l2 = RandomChoice[{True, False}, {2, 7 10^5}];
Argento[l2]
Brett[l2]
Artes[l2]
kguler[l2]
RM[l2]
1.4690000
0.5820000
0.3840000
0.3700000
0.2890000

Test III

l3 = RandomChoice[{True, False}, {2, 3 10^6}];
Argento[l3]
Brett[l3]
Artes[l3]
kguler[l3]
RM[l3]
6.2320000
2.4750000
1.6530000
1.4150000
1.2150000
$\endgroup$
3
  • 1
    $\begingroup$ \o/ yay, good timings for me! :D Usually all the fast ones are posted before I get here $\endgroup$
    – rm -rf
    Sep 4, 2012 at 21:49
  • $\begingroup$ @R.M These posts appear to be a good promotion of Inner! $\endgroup$
    – Artes
    Sep 4, 2012 at 21:57
  • $\begingroup$ @Artes, just added another one to benchmark... $\endgroup$
    – kale
    Sep 5, 2012 at 1:03
21
$\begingroup$

I prefer using Inner for this, as conceptually, it is a generalized dot of the two Boolean lists with And as the operator.

Inner[And, {True, True, False}, {True, False, False}, List]
(* {True, False, False} *)
$\endgroup$
4
  • $\begingroup$ This might give the Wizard a conniption ;) : {True, True, False} ~(Inner[And, ##, List] &)~ {True, False, False}. $\endgroup$ Sep 4, 2012 at 22:05
  • 3
    $\begingroup$ @J.M. You need to go deeper... {True, True, False} ~(And ~Sequence~ #1 ~Inner~ (#2 ~Sequence~ List) &)~ {True, False, False} INFIXTION $\endgroup$
    – rm -rf
    Sep 4, 2012 at 23:29
  • $\begingroup$ @R.M True ~Sequence~ True ~List~ False ~(Null ~Function~ (And ~Sequence~ #1 ~Inner~ (#2 ~Sequence~ List)))~ (True ~Sequence~ False ~List~ False) $\endgroup$ Sep 5, 2012 at 5:25
  • 1
    $\begingroup$ @OleksandrR. I once managed to really piss Mr.Wizard off by mocking him with a ~Rule~ b instead of the natural infix a -> b :) $\endgroup$
    – rm -rf
    Sep 5, 2012 at 5:30
17
$\begingroup$

I like Artes' and kguler's answers, but I'd like to point out that in general

f @@ # & /@ list

can be more concisely written as

f @@@ list

For example:

And @@@ Transpose[{{True, True, False}, {True, False, False}}]

(* {True, False, False} *)
$\endgroup$
13
$\begingroup$

You can use Thread:

Thread[And[{True, True, False}, {True, False, False}]]

or, Thread with Apply (@@) :

Thread[And@@{{True, True, False}, {True, False, False}}]
(* {True, False, False} *)
$\endgroup$
6
$\begingroup$

Late to the party

BitAnd @@ Boole@l /. {1 -> True, 0 -> False}
$\endgroup$
4
  • $\begingroup$ Why not simply BitAnd @@ Boole@l /. {1 -> True, 0 -> False}? What does Dispatch@ add? $\endgroup$
    – DavidC
    Sep 5, 2012 at 4:04
  • $\begingroup$ @DavidCarraher it adds a tiny bit of extra speed that I didn't expect either with such a short simple list of rules. I'll edit it out anyway to favour cleanliness $\endgroup$
    – Rojo
    Sep 5, 2012 at 11:03
  • $\begingroup$ +1 I thought about submitting BitAnd@@Boole@l myself but was disappointed that there was no short command to unBoole the outcome. Perhaps ReplaceAll is the best way to unBoole. $\endgroup$
    – DavidC
    Sep 5, 2012 at 13:04
  • $\begingroup$ @DavidCarraher, yeah, almost the same happened to me, disappointing, but I am more of a first post (then think/delete) person $\endgroup$
    – Rojo
    Sep 5, 2012 at 13:12
4
$\begingroup$

A silly one (convert both lists to numbers, multiply, convert back) and some timings:

(l1 /. {True -> 1, False -> 0}) (l2 /. {True -> 1, False -> 0}) /. {0 -> False, 1 -> True})

n = 1000000;
res = Table[
   l1 = RandomChoice[{True, False}, n];
   l2 = RandomChoice[{True, False}, n];
   {
    (r1 = And[l1, l2] // Thread) // AbsoluteTiming // First,
    (r2 = And @@@ Transpose[{l1, l2}]) // AbsoluteTiming // First,
    (r3 = MapThread[And, {l1, l2}]) // AbsoluteTiming // First,
    (r4 = Inner[And, l1, l2, List]) // AbsoluteTiming // First, 
    (r5 = (l1 /. {True -> 1, False -> 0}) (l2 /. {True -> 1, 
             False -> 0}) /. {0 -> False, 1 -> True}) // AbsoluteTiming // First
   }, {10}];

Mean /@ (res\[Transpose])

{0.3687211, 0.6879394, 0.5338305, 0.3507201, 0.7428425}

Inner wins.

$\endgroup$
1
  • 2
    $\begingroup$ @artes Yeah, I beat you by two minutes though ;-) Anyway, it confirms that Inner is the winner. $\endgroup$ Sep 4, 2012 at 21:41
4
$\begingroup$

I want in on this fun. Doesn't seem to be the fastest, but here it is:

l1={{True,True,False},{True,False,False}};
(# != 0) & /@ Times @@ Boole[l1];

(*{True,False,False}*)
$\endgroup$
0
2
$\begingroup$

And in a late bid for the silver medal by subversive means:

Unprotect@And; SetAttributes[And, {Flat, OneIdentity, Protected, Listable}];

l1 = RandomChoice[{True, False}, {2, 10^6}];

Argento[l1]
Brett[l1]
Artes[l1]
kguler[l1]
RM[l1]
And @@ l1 // AbsoluteTiming // First

0.705648 0.288288 0.193292 0.163886 0.149485 0.160957

$\endgroup$
4
  • 2
    $\begingroup$ That this is very close in performance to kguler's suggestion is no coincidence: setting Listable on something that ordinarily would not be just calls Thread automatically. The 2ms difference is probably not significant. And please, use Internal`InheritedBlock or similar when resetting attributes on system functions! $\endgroup$ Sep 5, 2012 at 6:30
  • $\begingroup$ @OleksandrR. Is there any documentation on InheritedBlock ? $\endgroup$ Sep 5, 2012 at 6:49
  • 2
    $\begingroup$ Alexey has written it up here, but there's no (public) official documentation that I know of. If you don't want to use undocumented functions, you can either use a Listable wrapper function, e.g. Function[Null, And[##], {Flat, Listable}] (though this is not very efficient), or just a normal Block. $\endgroup$ Sep 5, 2012 at 7:51
  • $\begingroup$ @OleksandrR. Thank you a very useful link. $\endgroup$ Sep 5, 2012 at 10:44

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.