12
$\begingroup$

I know there are a plenty of other questions here which appear to be similar, however I did not found anything which could give me a hint.

I have two lists:

list1 = {{A, 12}, {B, 10}, {C, 4}}; (*ordered according to the second column*) list2 = {{B, 5}, {A, 4}, {C, 1}}; (*ordered according to the second column*) 

Now I want to sort list2according to the list1-order so the output should be:

(* {{A, 4}, {B, 5}, {C, 1}} *) 
$\endgroup$
3
  • $\begingroup$ to be more specific list2should be sorted according to the first column of list1 $\endgroup$ Commented Mar 27, 2019 at 18:58
  • 1
    $\begingroup$ Is there a better example to show what you want? Doesn't Sort[list2] give the desired output? $\endgroup$ Commented Mar 27, 2019 at 23:24
  • 6
    $\begingroup$ list2[[OrderingBy[list1, -#[[2]] &]]] in the next release... $\endgroup$ Commented Mar 27, 2019 at 23:37

5 Answers 5

11
$\begingroup$
Permute[list2, FindPermutation[ list2[[All,1]] , list1[[All,1]] ] ] 

{{A, 4}, {B, 5}, {C, 1}}

$\endgroup$
2
  • $\begingroup$ Actually, I like your solution much better than mine. By the way, when I found out that my former solution was incorrect, I also realized that your solution should better be Permute[list2, FindPermutation[list2[[All, 1]], list1[[All, 1]]]]. $\endgroup$ Commented Mar 27, 2019 at 20:47
  • 1
    $\begingroup$ Doh...fixed it. Both ways give the same answer, which leads to sloppy debugging. $\endgroup$ Commented Mar 27, 2019 at 21:04
7
$\begingroup$
list1 = {{A, 12}, {B, 10}, {C, 4}, {D, 2}}; list2 = {{A, 4}, {D, 11}, {B, 5}, {C, 1}}; idx = Lookup[ AssociationThread[list1[[All, 1]] -> Range[Length[list1]]], list2[[All, 1]] ]; result = list2; result[[idx]] = list2; result 

{{A, 4}, {B, 5}, {C, 1}, {D, 11}}

$\endgroup$
1
  • $\begingroup$ works well with the example lists. However, something goes wrong when I use other lists with Strings in the first columns instead of A, Band C.... $\endgroup$ Commented Mar 27, 2019 at 21:29
6
$\begingroup$

ugly but fast:

list2[[Ordering[list2[[All, 1]]][[Ordering[Ordering[list1[[All, 1]]]]]]]] 

{{A, 4}, {B, 5}, {C, 1}}

even faster:

result = list2; result[[Ordering[list1[[All, 1]]]]] = SortBy[list2, First]; result 

{{A, 4}, {B, 5}, {C, 1}}

benchmarks

s = 10^7; list1 = Transpose[{PermutationList@RandomPermutation[s], RandomInteger[{0, 10}, s]}]; list2 = Transpose[{PermutationList@RandomPermutation[s], RandomInteger[{0, 10}, s]}]; (* my first solution *) result1 = list2[[Ordering[list2[[All, 1]]][[Ordering[Ordering[list1[[All, 1]]]]]]]]; //AbsoluteTiming//First (* 8.6416 *) (* my second solution *) result2 = Module[{L}, L = list2; L[[Ordering[list1[[All, 1]]]]] = SortBy[list2, First]; L]; //AbsoluteTiming//First (* 6.89593 *) (* MikeY's solution *) result3 = Permute[list2, FindPermutation[list2[[All, 1]], list1[[All, 1]]]]; //AbsoluteTiming//First (* 15.808 *) (* Henrik Schumacher's solution *) result4 = Module[{idx, L}, idx = Lookup[AssociationThread[list1[[All, 1]] -> Range[Length[list1]]], list2[[All, 1]]]; L = list2; L[[idx]] = list2; L]; //AbsoluteTiming//First (* 31.7412 *) (* make sure all methods agree *) result1 == result2 == result3 == result4 (* True *) 
$\endgroup$
1
  • $\begingroup$ Thanks for the benchmark. I started down the Ordering road, but went for parsimony of expression. Mild bummer that it is at least twice as slow as the best method. $\endgroup$ Commented Mar 27, 2019 at 23:34
2
$\begingroup$
p = {{a, 12}, {b, 10}, {c, 4}}; q = {{b, 5}, {a, 4}, {c, 1}}; n = Length[p]; 

Using SubsetMap (new in 12.0)

SubsetMap[Last /@ Sort[q] &, p, Table[{i, 2}, {i, n}]] 

{{a, 4}, {b, 5}, {c, 1}}

$\endgroup$
2
$\begingroup$
l1 = {{a, 12}, {b, 10}, {c, 4}}; l2 = {{b, 5}, {a, 4}, {c, 1}}; 

Using OrderingBy and RotateLeft:

l2[[RotateLeft@OrderingBy[l1, Last]]] (*{{a, 4}, {b, 5}, {c, 1}}*) 
$\endgroup$

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.