7

How can I order a list to match the order of anoter list ?

For example: Suppose I have the lists x = {3, 1, 5, 7} and y = {3, 7, 1, 5}. How can I order x to have the order of y?

This question is interesting when each element of x has composite values, for example, as a list or an association.

m_goldberg
  • 107,779
  • 16
  • 103
  • 257
faysou
  • 10,999
  • 3
  • 50
  • 125

2 Answers2

11

Using Ordering it's possible to do this. Ordering can be seen as a permutation that brings a list to the identity permutation. And applying Ordering again to this permutation we get the inverse permutation that brings a list from identity to the original order. Using these observations:

OrderingToTarget[list_, sourceIds_, targetIds_] :=
  list[[Ordering @ sourceIds]][[Ordering @ Ordering@targetIds]]

OrderingToTarget[x, x, y]
faysou
  • 10,999
  • 3
  • 50
  • 125
  • 1
    You are right, it is fast and traditional way to do a such kind of sorting. Related: 1, 2, 3. Anyway, +1, I cannot find similar Q&A. – ybeltukov Nov 21 '15 at 16:05
2

Inspired by Sort two lists at the same time, based on another here is a different approach:

permuteLike[a_, b_] :=
  Module[{x = a},
    x[[Ordering @ b]] = Sort[a];
    x
  ]

This proves to be somewhat faster and I find it somehow more pleasing as well.

a = {"f", "a", "h", "y", "c", "d"};
b = {"w", "t", "q", "o", "b", "p"};

OrderingToTarget[a, a, b]

a ~permuteLike~ b
{"y", "h", "f", "c", "a", "d"}

{"y", "h", "f", "c", "a", "d"}

{a, b} = RandomInteger[3*^6, {2, 1*^6}];

OrderingToTarget[a, a, b] // RepeatedTiming // First

a ~permuteLike~ b         // RepeatedTiming // First
0.3234

0.228

Mr.Wizard
  • 271,378
  • 34
  • 587
  • 1,371