6
$\begingroup$

I have two tables, each having three rows (R1, R2 & R3). The elements of R2 & R3 are same in two tables but in different orders. The elements in row R1 are different in two tables. I want to sort the elements of second table such that rows R2 & R3 become similar. For example, If

T1 = {{t1, 1, 2}, {t2, 2, 3}, {t3, 3, 2}, {t4, 2, 1}}

T2 = {{u1, 3, 2}, {u2, 1, 2}, {u3, 2, 1}, {u4, 2, 3}}

How can I sort elements of T2 such that second and third elements of each row are same as T1. That is

T3 = {{u2, 1, 2}, {u4, 2, 3}, {u1, 3, 2}, {u3, 2, 1}}

thanks

$\endgroup$
3
  • 1
    $\begingroup$ Are there duplicate values in the 2nd and 3rd columns of the table? $\endgroup$
    – Szabolcs
    Commented Sep 30, 2017 at 8:52
  • $\begingroup$ For example {t1, 1, 2} and {t2, 2, 1} are possible at same time, so are {t1, 1, 1} and {t2, 2, 2}. But {t1, 1, 2 } and {t2, 1, 2} are not possible. For a set of last two elements, first row can't have two different elements. thanks $\endgroup$
    – user49535
    Commented Sep 30, 2017 at 9:07
  • $\begingroup$ Then the association method will work. $\endgroup$
    – Szabolcs
    Commented Sep 30, 2017 at 9:17

2 Answers 2

4
$\begingroup$

There are multiple ways. One is to use Ordering.

Let p1 and p2 be the permutations that order T1 and T2 by their R2 & R3.

p1 = Ordering[T1[[All, 2 ;; 3]]]
(* {1, 4, 2, 3} *)

p2 = Ordering[T2[[All, 2 ;; 3]]]
(* {2, 3, 4, 1} *)

Let's invert p1:

invp1 = Ordering[p1]
(* {1, 3, 4, 2} *)

Then we sort T2, then transform that to the order seen in T1:

T2[[p2]][[invp1]]
(* {{u2, 1, 2}, {u4, 2, 3}, {u1, 3, 2}, {u3, 2, 1}} *)

Another way is to use Association

a1 = AssociationThread[
  T1[[All, 2 ;; 3]],
  T1[[All, 1]]
  ]
(* <|{1, 2} -> t1, {2, 3} -> t2, {3, 2} -> t3, {2, 1} -> t4|> *)

a2 = AssociationThread[
  T2[[All, 2 ;; 3]],
  T2[[All, 1]]
  ]
(* <|{3, 2} -> u1, {1, 2} -> u2, {2, 1} -> u3, {2, 3} -> u4|> *)

This assumes that there were no duplicates {R2, R3} pairs.

KeyTake[a2, Keys[a1]]
(* <|{1, 2} -> u2, {2, 3} -> u4, {3, 2} -> u1, {2, 1} -> u3|> *)

If you have Mathematica 10.0+ and no trouble with duplicate keys, I would use the association-based method, and I would keep the data structures as associations instead of tables.

$\endgroup$
4
  • $\begingroup$ Thanks. Association is working fine for me..One more thing, how can I convert <|{1, 2} -> u2, {2, 3} -> u4, {3, 2} -> u1, {2, 1} -> u3|> back to table form like {{u2, 1, 2}, {u4, 2, 3}, {u1, 3, 2}, {u3, 2, 1}}. $\endgroup$
    – user49535
    Commented Sep 30, 2017 at 10:21
  • $\begingroup$ I tried - MapThread[Append, {Values[KeyTake[a2, Keys[a1]]], Keys[KeyTake[a2, Keys[a1]]]}] but coming back with error Append::normal: Nonatomic expression expected at position 1 in Append[u2,{1,2}]. $\endgroup$
    – user49535
    Commented Sep 30, 2017 at 10:44
  • $\begingroup$ @user49535 KeyValueMap[Prepend, ...]. But if you need the table form, use the full lists as association values instead of just the first element. Then you can just use Values in the end. $\endgroup$
    – Szabolcs
    Commented Sep 30, 2017 at 11:31
  • $\begingroup$ I am struggling with this small issue, can you please elaborate. Not able to get back {{u2, 1, 2}, ....} by any method. Could this be because of u2 not being a numerical value ? $\endgroup$
    – user49535
    Commented Oct 1, 2017 at 10:44
2
$\begingroup$

In addition to @Szabolcs's method, a more straightforward approach might be SortBy:

SortBy[T2, Position[T1[[All, 2 ;; 3]], #[[2 ;; 3]]] &]
(* {{u2, 1, 2}, {u4, 2, 3}, {u1, 3, 2}, {u3, 2, 1}} *)

which gives the answer you want.

$\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.