4
$\begingroup$

Suppose I have two lists of the same size as follows:

A1 = {a, b, c, d};
A2 = {c, a, b, d};

I want to construct a function that gives the relation between positions of same elements in both lists.

For example, we see that

a = A1[[1]] = A2[[2]]
b = A1[[2]] = A2[[3]]

and so on.

With DeleteCases and using Alternatives, I can tell whether the two elements of two lists are the same or not, but I can not tell which position of them are in the same.

Is there any smart way to find out their relations? In the above example, I want the code to return a list:

{{1, 2}, {2, 3}, {3, 1}, {4, 4}}
$\endgroup$

7 Answers 7

7
$\begingroup$

Update

Ben Izd (in a comment) has suggested the following neat modification: Use Catenate rather than Identity to avoid mapping Flatten

Merge[PositionIndex/@{A1,A2},Catenate]

(* <|a -> {1, 2}, b -> {2, 3}, c -> {3, 1}, d -> {4, 4}|> *)

Original Answer

Merge[{PositionIndex[A1],PositionIndex[A2]},Identity]

(* <|a -> {{1}, {2}}, b -> {{2}, {3}}, c -> {{3}, {1}}, d -> {{4}, {4}}|> *)

Or:

Map[Flatten,Merge[{PositionIndex[A1],PositionIndex[A2]},Identity]]

%//Values

(* 
  <|a -> {1, 2}, b -> {2, 3}, c -> {3, 1}, d -> {4, 4}|>

  {{1, 2}, {2, 3}, {3, 1}, {4, 4}} 
*)
$\endgroup$
1
  • 3
    $\begingroup$ (+1) You can replace Identity with Catenate to skip mapping Flatten. $\endgroup$
    – Ben Izd
    Aug 16, 2023 at 4:55
6
$\begingroup$

You can use Ordering

ar1 = {a, b, c, d}
ar2 = {c, a, b, d}

Thread[Ordering /@ {ar1, ar2}]

yields: {{1, 2}, {2, 3}, {3, 1}, {4, 4}}

$\endgroup$
4
$\begingroup$

Using Permutation:

Transpose@{Range[Length[A1]], 
  PermutationList[FindPermutation[A1, A2], Length[A1]]}

(* Out: {{1, 2}, {2, 3}, {3, 1}, {4, 4}} *)
$\endgroup$
4
$\begingroup$

Using Query and Dataset:

Query[Merge[#, Flatten] & /* Dataset, PositionIndex][{A1, A2}]

enter image description here

Add Headers with subquery:

ds =
 Query[Merge[#, Flatten] & /*
       Query[All, AssociationThread[{"A1", "A2"} -> #] &] @ # & /* Dataset,
   PositionIndex][{A1, A2}]

enter image description here

Now, for example:

ds[{Key @ a, Key @ d}, "A2"]

enter image description here

$\endgroup$
4
$\begingroup$

Using DistanceMatrix:

Position[DistanceMatrix[A1, A2], 0]

Using Position:

Transpose@{Range@Length@A1, Flatten[Position[A2, #] & /@ A1]}

Using OrderingBy:

MapIndexed[{First@#2, #1} &, OrderingBy[A2, Position[A1, #] &]]

Result

{{1, 2}, {2, 3}, {3, 1}, {4, 4}}

$\endgroup$
3
$\begingroup$

One possible way

A1={a,b,c,d};
A2={c,a,b,d};

MapIndexed[{First[#2], Flatten@Position[A2, #1]} &, A1]

Mathematica graphics

If you only want the first position that match, add First

 MapIndexed[{First[#2],First@Flatten@Position[A2,#1]}&,A1]

Mathematica graphics

$\endgroup$
2
$\begingroup$

Another way using GroupBy:

Values@Merge[Keys@GroupBy[{A1, A2}, PositionIndex], Join @@ # &]

(*{{1, 2}, {2, 3}, {3, 1}, {4, 4}}*)
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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