23

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.

rm -rf
  • 88,781
  • 21
  • 293
  • 472
ArgentoSapiens
  • 7,780
  • 1
  • 32
  • 49

8 Answers8

23

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
Artes
  • 57,212
  • 12
  • 157
  • 245
21

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} *)
rm -rf
  • 88,781
  • 21
  • 293
  • 472
  • This might give the Wizard a conniption ;) : {True, True, False} ~(Inner[And, ##, List] &)~ {True, False, False}. – J. M.'s missing motivation Sep 04 '12 at 22:05
  • 3
    @J.M. You need to go deeper... {True, True, False} ~(And ~Sequence~ #1 ~Inner~ (#2 ~Sequence~ List) &)~ {True, False, False} INFIXTION – rm -rf Sep 04 '12 at 23:29
  • @R.M True ~Sequence~ True ~List~ False ~(Null ~Function~ (And ~Sequence~ #1 ~Inner~ (#2 ~Sequence~ List)))~ (True ~Sequence~ False ~List~ False) – Oleksandr R. Sep 05 '12 at 05:25
  • 1
    @OleksandrR. I once managed to really piss Mr.Wizard off by mocking him with a ~Rule~ b instead of the natural infix a -> b :) – rm -rf Sep 05 '12 at 05:30
17

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} *)
Brett Champion
  • 20,779
  • 2
  • 64
  • 121
13

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} *)
kglr
  • 394,356
  • 18
  • 477
  • 896
6

Late to the party

BitAnd @@ Boole@l /. {1 -> True, 0 -> False}
Rojo
  • 42,601
  • 7
  • 96
  • 188
  • Why not simply BitAnd @@ Boole@l /. {1 -> True, 0 -> False}? What does Dispatch@ add? – DavidC Sep 05 '12 at 04:04
  • @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 – Rojo Sep 05 '12 at 11:03
  • +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. – DavidC Sep 05 '12 at 13:04
  • @DavidCarraher, yeah, almost the same happened to me, disappointing, but I am more of a first post (then think/delete) person – Rojo Sep 05 '12 at 13:12
4

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.

Sjoerd C. de Vries
  • 65,815
  • 14
  • 188
  • 323
4

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}*)
kale
  • 10,922
  • 1
  • 32
  • 69
2

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

image_doctor
  • 10,234
  • 23
  • 40
  • 2
    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! – Oleksandr R. Sep 05 '12 at 06:30
  • @OleksandrR. Is there any documentation on InheritedBlock ? – image_doctor Sep 05 '12 at 06:49
  • 2
    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. – Oleksandr R. Sep 05 '12 at 07:51
  • @OleksandrR. Thank you a very useful link. – image_doctor Sep 05 '12 at 10:44