22
$\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$
  • 4
    $\begingroup$ +1 Nice question, invites many possible responses. $\endgroup$ – DavidC Sep 4 '12 at 16:51
  • $\begingroup$ Related: (3217) $\endgroup$ – Mr.Wizard Jan 18 '15 at 15:30
20
$\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$
  • 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 '12 at 21:49
  • $\begingroup$ @R.M These posts appear to be a good promotion of Inner! $\endgroup$ – Artes Sep 4 '12 at 21:57
  • $\begingroup$ @Artes, just added another one to benchmark... $\endgroup$ – kale Sep 5 '12 at 1:03
19
$\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$
  • $\begingroup$ This might give the Wizard a conniption ;) : {True, True, False} ~(Inner[And, ##, List] &)~ {True, False, False}. $\endgroup$ – J. M. is away Sep 4 '12 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 '12 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$ – Oleksandr R. Sep 5 '12 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 '12 at 5:30
16
$\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$
12
$\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$
5
$\begingroup$

Late to the party

BitAnd @@ Boole@l /. {1 -> True, 0 -> False}
$\endgroup$
  • $\begingroup$ Why not simply BitAnd @@ Boole@l /. {1 -> True, 0 -> False}? What does Dispatch@ add? $\endgroup$ – DavidC Sep 5 '12 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 '12 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 '12 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 '12 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$
  • 2
    $\begingroup$ @artes Yeah, I beat you by two minutes though ;-) Anyway, it confirms that Inner is the winner. $\endgroup$ – Sjoerd C. de Vries Sep 4 '12 at 21:41
3
$\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$
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$
  • 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$ – Oleksandr R. Sep 5 '12 at 6:30
  • $\begingroup$ @OleksandrR. Is there any documentation on InheritedBlock ? $\endgroup$ – image_doctor Sep 5 '12 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$ – Oleksandr R. Sep 5 '12 at 7:51
  • $\begingroup$ @OleksandrR. Thank you a very useful link. $\endgroup$ – image_doctor Sep 5 '12 at 10:44

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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