Find positions in which list elements are equal
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
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}
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}};
Position[MapThread[Equal, {a, b}], True]
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}];
RepeatedTiming@Position[MapThread[Equal, {a, b}], True][[1]]
(*0.089*)
RepeatedTiming@
Position[Unitize[Subtract[a, b]].ConstantArray[1,
Dimensions[a][[2]]], 0, 1][[1]]
(*0.0057*)