Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

I would like to compare two arrays:

m = {a,b,c,d,d,f};
n = {b,b,a,d,d,e};

and get:

{0,b,0,d,d,0}

I have tried all kinds of things, like:

m = {a,b,c,d,d,f};
n = {b,b,a,d,d,e};
Transpose[{m, n}];
If[{x_ == y_} :> x, 0]

but clearly, I have no idea what I am doing! I am (obviously) very new to Mathematica, and would greatly appreciate any help.

share|improve this question
    
Will the elements always be symbols, or will they sometimes be values, or characters/strings? –  Pickett Oct 9 '13 at 17:16

11 Answers 11

up vote 18 down vote accepted

The following solution may look a bit weird, but has an advantage of automatically being very efficient for numerical large lists:

m * (1 - Block[{Unitize}, _Unitize = 1; #] & [ Unitize[m - n]])
share|improve this answer
    
+1. Are you still going to write that part 2 of your book? I know you're super busy, just curious. –  RunnyKine Oct 9 '13 at 17:38
2  
@RunnyKine Thanks. Re: book - yes, I am going to, although it is not yet clear what the format of it will be, or set the exact time frame for it. –  Leonid Shifrin Oct 9 '13 at 17:42
    
Thanks for replying. Good to know. The first one is a classic by the way. –  RunnyKine Oct 9 '13 at 17:45
    
@RunnyKine Well, thanks :) I wrote it when I knew so much less than I do now (which I do in a big part due to this community), and I can see many flaws in the book now - so it's always good to know that it is not totally bad :) –  Leonid Shifrin Oct 9 '13 at 17:47
    
Thanks, Leonid - very fast! –  martin Oct 9 '13 at 18:21
MapThread[If[SameQ[#1, #2], #1, 0] &, {m, n}]

or

Transpose[{m, n}] /. {p_, q_} :> If[SameQ[p, q], p, 0]
share|improve this answer
    
Many thanks, Chris! –  martin Oct 9 '13 at 17:24
Inner[ If[ #1 === #2, #1, 0] &, m, n, List]
{0, b, 0, d, d, 0}

or with Transpose and Apply:

If[#1 === #2, #1, 0] & @@@ Transpose[{m, n}]
share|improve this answer

Here's an unconventional way, which I think should be reasonably fast (thanks to Leonid for spotting a flaw):

Replace[m + n, _Plus -> 0, {1}] / 2
(* {0, b, 0, d, d, 0} *)

The idea is that a + b will have the head Plus, whereas a + a is 2 a, which has the head Times. Needless to say, a severe drawback of this approach is when the elements of the lists are numbers...

share|improve this answer
    
+1, this is a nice one. –  Leonid Shifrin Oct 9 '13 at 17:58
    
@LeonidShifrin Oops... Thanks! :D –  rm -rf Oct 9 '13 at 17:59
    
+1. Yeah this is nice. –  RunnyKine Oct 9 '13 at 18:03

And yet another variation using rules:

Thread@{m, n} /. {{p_, p_} :> p, {_, _} :> 0}

(Also Thread instead of Transpose for extra differenceness)

share|improve this answer

Here's a straightforward approach quite similar to your first attempt, which has the feature that it will work for numbers as well as symbols.

m = {1, b, c, 5.0, d, f};
n = {3, b, a, 5.0, d, e};
Table[If[m[[i]] === n[[i]], m[[i]], 0], {i, Length[m]}]

{0, b, 0, 5., d, 0}
share|improve this answer
m (1 - Sign[Length /@ (m - n)])
(*{0, b, 0, d, d, 0}*)
share|improve this answer

My solution:

m * Boole@MapThread[SameQ, {m, n}]

{0, b, 0, d, d, 0}


And here's the comparison:

m = RandomChoice[{a, b, c, d, e, f, g, h, i, j, k}, 1000000];
n = RandomChoice[{a, b, c, d, e, f, g, h, i, j, k}, 1000000];

(*Leonid Shifrin*)
m*(1 - Block[{Unitize}, _Unitize = 1; #] &[Unitize[m - n]]); // AbsoluteTiming

(*Artes*)
Inner[If[#1 === #2, #1, 0] &, m, n, List]; // AbsoluteTiming

(*Artes*)
If[#1 === #2, #1, 0] & @@@ Transpose[{m, n}]; // AbsoluteTiming

(*Chris Degnen*)
MapThread[If[SameQ[#1, #2], #1, 0] &, {m, n}]; // AbsoluteTiming

(*Chris Degnen*)
Transpose[{m, n}] /. {p_, q_} :> If[SameQ[p, q], p, 0]; // AbsoluteTiming

(*rm-rf*)
Replace[m + n, _Plus -> 0, {1}]/2; // AbsoluteTiming(*rm-rf*)

(*wxffles*)
Thread@{m, n} /. {{p_, p_} :> p, {_, _} :> 0}; // AbsoluteTiming

(*chyaong*)
m (1 - Sign[Length /@ (m - n)]); // AbsoluteTiming

(*RunnyKine*)
n*Replace[m/n, {1 -> 1, _ -> 0}, {1}]; // AbsoluteTiming

(*alephalpha*)
m * Boole@MapThread[SameQ, {m, n}]; // AbsoluteTiming

{5.359334, Null}
{1.688222, Null}
{1.920503, Null}
{1.629107, Null}
{2.132745, Null}
{1.964956, Null}
{1.396690, Null}
{3.478013, Null}
{3.582479, Null}
{1.933204, Null}

share|improve this answer
    
@Artes It refers to Loenid's one. –  alephalpha Oct 11 '13 at 16:32

With inspiration from rm -rf here's one that should also work with numbers (If there are no zeros).

n * Replace[m / n, {1 -> 1, _ -> 0}, {1}]

{0, b, 0, d, d, 0}

share|improve this answer

Here is another one:

m * (1 - Abs[MapThread[Order, {m, n}]])
share|improve this answer

Idea of sparseArray can be pretty useful in case of large matrices or on extending it to multi-dimensional.

Block[{m = {a, b, c, d, d, f}, n = {b, b, a, d, d, e}, sep, 
  sum}, {sep = ArrayPad[#, {0, Length[m] - Length[#]}] & /@ 
    Flatten[Normal[SparseArray[{1, #} -> n[[#]]]] & /@ 
      Flatten[Position[Subtract[m, n], 0]], 1], 
  sum = ConstantArray[0, Length[m]]}; 
 Table[sum = sep[[i]] + sum, {i, Length[sep]}] // Last]

{0, b, 0, d, d, 0}

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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