# Find positions in which list elements are equal

So I have 2 lists of 10000+ lists of 3 numbers, e.g.

{{1,2,3},{4,5,6},{7,8,9},...}
{{2,1,3},{4,5,6},{41,2,0},...}


Wanting a result like

{2,...}


Getting some sort of list of True/False is also probably enough, like this:

{False,True,False,...}


I guess I could use Position once I've done that.

I tried to use Thread, as below:

Thread[{{a, b}, {c, d}, {e, f}} == {{a, b}, {d, e}, {f, e}}]


which gives the True/False output

{True, {c, d} == {d, e}, {e, f} == {f, e}}


But as soon as there are actual numbers in place, it doesn't work:

Thread[{{1, 2}, {2, 3}, {4, 5}} == {{1, 3}, {2, 3}, {4, 5}}]


Returns

False


Thanks,

H

One possible way of doing it:

a = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}, {1, 2, 3}};
b = {{2, 1, 3}, {4, 5, 6}, {41, 2, 0}, {1, 2, 3}};


The output reads: {{2}, {4}}

In my code, it compares the elements for each position, but it doesn't "cross check" them, i.e.it doesn't consider that the element n of list a could be equal to element m!=n of list b

EDIT: note that the solution provided by @Henrik Schumacher is much faster :)

a = RandomInteger[{0, 4}, {100000, 3}];
b = RandomInteger[{0, 4}, {100000, 3}];

(*0.089*)

RepeatedTiming@
Position[Unitize[Subtract[a, b]].ConstantArray[1,
Dimensions[a][[2]]], 0, 1][[1]]
(*0.0057*)

• That's perfect and very simple. I tried to do a similar thing but I guess I messed up the syntax or something. Indeed I didn't want any cross-checking, comparing like-for-like position is an important part of my problem. Thanks so much! I'll mark as the answer as soon as I can
– H94
Commented Jun 5, 2018 at 8:10
a = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}, {1, 2, 3}};
b = {{2, 1, 3}, {4, 5, 6}, {41, 2, 0}, {1, 2, 3}};

Pick[Range@Length@a, Total /@ Unitize[Subtract[a, b]], 0]


{2,4}

Or using @Henrik's idea of using Dot in in the second argument of Pick:

Pick[Range @ Length @ a,
Unitize[Subtract[a, b]].ConstantArray[1, Dimensions[a][[2]]], 0]


{2, 4}

This should be rather fast for very long packed arrays of integers.

a = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}, {1, 2, 3}};
b = {{2, 1, 3}, {4, 5, 6}, {41, 2, 0}, {1, 2, 3}};
f2[a_,b_] := Position[Unitize[Subtract[a, b]].ConstantArray[1, Dimensions[a][[2]]], 0, 1];

f2[a,b]


{{2}, {4}}

More complicated but twice as fast (thanks to Carl Woll for the idea to use 1. instead of 1 in the ConstantArray):

f3[a_, b_] := SparseArray[
Unitize[
Unitize[Subtract[a, b]].ConstantArray[1., Dimensions[a][[2]]]],
{Length[a]},
1
]["NonzeroPositions"];

RandomSeed[12345];
{a, b} = RandomInteger[{1, 9}, {2, 1000000, 3}];

r2 = f2[a, b]; // RepeatedTiming // First
r3 = f3[a, b]; // RepeatedTiming // First
r2 == r3


0.060

0.021

True

• Using ConstantArray[1., Dimensions[a][[2]]] is a bit faster Commented Jun 5, 2018 at 18:46
• Thanks, @CarlWoll, that's very good thing to keep in mind! Commented Jun 5, 2018 at 21:46

If you need speed, you could use ugly compiled function:

equalPosInt2 = Last@Compile[{{a, _Integer, 2}, {b, _Integer, 2}},
Module[{result, dimA, dimB, n, m, eq},
result = InternalBag@Most@{0};
dimA = Dimensions@a;
dimB = Dimensions@b;
n = Min[CompileGetElement[dimA, 1], CompileGetElement[dimB, 1]];
m = Min[CompileGetElement[dimA, 2], CompileGetElement[dimB, 2]];
Do[
eq = True;
Do[
If[CompileGetElement[a, i, j] =!= CompileGetElement[b, i, j],
eq = False;
Break[];
];
,
{j, m}
];
If[eq, InternalStuffBag[result, i]];
,
{i, n}
];
InternalBagPart[result, All]
],
CompilationTarget -> "C", RuntimeOptions -> "Speed"
];


Basic test:

a = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}, {1, 2, 3}};
b = {{2, 1, 3}, {4, 5, 6}, {41, 2, 0}, {1, 2, 3}};
equalPosInt2[a, b]
(* {2, 4} *)


Timings:

fraccalo[a_, b_] := Position[MapThread[Equal, {a, b}], True]
f2[a_, b_] := Position[Unitize[Subtract[a, b]].ConstantArray[1, Dimensions[a][[2]]], 0, 1]
f3[a_, b_] := SparseArray[Unitize[Unitize[Subtract[a, b]].ConstantArray[1, Dimensions[a][[2]]]], {Length[a]}, 1]["NonzeroPositions"]
kglr1[a_, b_] := Pick[Range@Length@a, Total /@ Unitize[Subtract[a, b]], 0]
kglr2[a_, b_] := Pick[Range@Length@a, Unitize[Subtract[a, b]].ConstantArray[1, Dimensions[a][[2]]], 0]

RandomSeed@12345;
{a, b} = RandomInteger[{1, 9}, {2, 1000000, 3}];

r1 = fraccalo[a, b]; // MaxMemoryUsed // RepeatedTiming     (*{0.691, 280000672}*)
r2 = f2[a, b]; // MaxMemoryUsed // RepeatedTiming           (*{0.0803, 64000928}*)
r3 = f3[a, b]; // MaxMemoryUsed // RepeatedTiming           (*{0.048,  64001120}*)
r4 = kglr1[a, b]; // MaxMemoryUsed // RepeatedTiming        (*{0.072,  56000904}*)
r5 = kglr2[a, b]; // MaxMemoryUsed // RepeatedTiming        (*{0.0495, 72001232}*)
r6 = equalPosInt2[a, b]; // MaxMemoryUsed // RepeatedTiming (*{0.0054,    29928}*)

r1[[All, 1]] === r2[[All, 1]] === r3[[All, 1]] === r4 === r5 === r6
(* True *)
`