11
$\begingroup$

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.

$\endgroup$
  • $\begingroup$ Will the elements always be symbols, or will they sometimes be values, or characters/strings? $\endgroup$ – C. E. Oct 9 '13 at 17:16

11 Answers 11

18
$\begingroup$

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]])
$\endgroup$
  • $\begingroup$ +1. Are you still going to write that part 2 of your book? I know you're super busy, just curious. $\endgroup$ – RunnyKine Oct 9 '13 at 17:38
  • 2
    $\begingroup$ @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. $\endgroup$ – Leonid Shifrin Oct 9 '13 at 17:42
  • $\begingroup$ Thanks for replying. Good to know. The first one is a classic by the way. $\endgroup$ – RunnyKine Oct 9 '13 at 17:45
  • $\begingroup$ @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 :) $\endgroup$ – Leonid Shifrin Oct 9 '13 at 17:47
10
$\begingroup$
MapThread[If[SameQ[#1, #2], #1, 0] &, {m, n}]

or

Transpose[{m, n}] /. {p_, q_} :> If[SameQ[p, q], p, 0]
$\endgroup$
  • $\begingroup$ Many thanks, Chris! $\endgroup$ – martin Oct 9 '13 at 17:24
8
$\begingroup$
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}]
$\endgroup$
5
$\begingroup$

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...

$\endgroup$
  • $\begingroup$ @LeonidShifrin Oops... Thanks! :D $\endgroup$ – rm -rf Oct 9 '13 at 17:59
5
$\begingroup$

And yet another variation using rules:

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

(Also Thread instead of Transpose for extra differenceness)

$\endgroup$
4
$\begingroup$

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}
$\endgroup$
3
$\begingroup$
m (1 - Sign[Length /@ (m - n)])
(*{0, b, 0, d, d, 0}*)
$\endgroup$
2
$\begingroup$

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}

$\endgroup$
  • $\begingroup$ @Artes It refers to Loenid's one. $\endgroup$ – alephalpha Oct 11 '13 at 16:32
1
$\begingroup$

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}

$\endgroup$
1
$\begingroup$

Here is another one:

m * (1 - Abs[MapThread[Order, {m, n}]])
$\endgroup$
0
$\begingroup$

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}

$\endgroup$

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.