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$
  • 1
    $\begingroup$ Are there duplicate values in the 2nd and 3rd columns of the table? $\endgroup$ – Szabolcs Sep 30 '17 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 Sep 30 '17 at 9:07
  • $\begingroup$ Then the association method will work. $\endgroup$ – Szabolcs Sep 30 '17 at 9:17
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$
  • $\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 Sep 30 '17 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 Sep 30 '17 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 Sep 30 '17 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 Oct 1 '17 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, privacy policy and cookie policy

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