10
$\begingroup$

Suppose I have the following list:

Tl={{a, 3, b}, {c, 6, d}, {e, 9, f}, {g, 5, h}}

I really want to reverse specific elements of this list such that I get the following:

lT= {{b,5, a}, {d, 9, c}, {f, 6, e}, {h, 3, g}}

The best I could do is:

Reverse /@ tl

(* output: {{b, 3, a}, {d, 6, c}, {f, 9, e}, {h, 5, g}} *)

Any suggestions? The method should hold for any even number (say N) of sublists (consisting of 3 elements) in the original data set. As can be seen, N=4 for this case.

$\endgroup$
3
  • $\begingroup$ lt=tl;lt[[All,2]]=Reverse@lt[[All,2]] $\endgroup$
    – ciao
    Commented Oct 5, 2015 at 6:04
  • 2
    $\begingroup$ @ciao I also think the first and third elements are reversed $\endgroup$ Commented Oct 5, 2015 at 6:20
  • $\begingroup$ @PeterRoberge: Yep, missed that... $\endgroup$
    – ciao
    Commented Oct 5, 2015 at 6:51

4 Answers 4

7
$\begingroup$

I'll solve this in two parts to better see what's going on.

(changing variable to t)

t = {{a, 3, b}, {c, 6, d}, {e, 9, f}, {g, 5, h}}

Part one will create sub-lists of the first and third element of each list:

p1 = Map[Reverse, t[[All, {1, 3}]]]

{{b, a}, {d, c}, {f, e}, {h, g}}

Part two will reverse the second element:

p2 = Reverse [t[[All, 2]]]

{5, 9, 6, 3}

Then put it all back together:

Transpose[{p1[[All, 1]], p2[[All]], p1[[All, 2]]}]

{{b, 5, a}, {d, 9, c}, {f, 6, e}, {h, 3, g}}
$\endgroup$
9
$\begingroup$
Transpose[{#[[;; , 3]], #[[-1 ;; 1 ;; -1, 2]], #[[;; , 1]]}] &@lt

or

Transpose[{#3, Reverse[#2], #1}] & @@ Transpose[lt]
$\endgroup$
7
  • 1
    $\begingroup$ Nice use of apply, +1 $\endgroup$
    – LLlAMnYP
    Commented Oct 5, 2015 at 6:36
  • $\begingroup$ This is a beauty! $\endgroup$
    – thils
    Commented Oct 5, 2015 at 6:37
  • $\begingroup$ @LLlAMnYP thanks, but I still feel like we are missing a shorter solution :) $\endgroup$
    – Kuba
    Commented Oct 5, 2015 at 6:37
  • 2
    $\begingroup$ Thread[{#3,Reverse@#2,#1}&@@Transpose@m] is 5 characters shorter than yours. I don't see a shorter solution... (and that's mostly thanks to syntactic sugar) $\endgroup$
    – LLlAMnYP
    Commented Oct 5, 2015 at 6:46
  • 1
    $\begingroup$ @LLlAMnYP Keep in mind you can use :tr: syntax too :) $\endgroup$
    – Kuba
    Commented Oct 5, 2015 at 7:11
9
$\begingroup$

Here's a one-liner:

m = {{a, 3, b}, {c, 6, d}, {e, 9, f}, {g, 5, h}}

Reverse /@ Transpose@MapAt[Reverse, Transpose[m], 2]

(* {{b, 5, a}, {d, 9, c}, {f, 6, e}, {h, 3, g}} *)

Here's another one:

MapThread[Riffle, {m[[All, {3, 1}]], m[[-1 ;; 1 ;; -1, {2}]]}]

And another:

Thread[{m[[All, 3]], m[[-1 ;; 1 ;; -1, 2]], m[[All, 1]]}]

Also, as suggested by @Kuba, which is shorter yet in the notebook. Unfortunately, the font in the editor doesn't support the superscripted "T" for transposition (it's unicode F3C7), so it doesn't look as nice here. is equivalent to :tr:.

{#3, Reverse@#2, #1} & @@ (m)

The challenge remains to make this even shorter.

$\endgroup$
1
  • $\begingroup$ Both are good answers! $\endgroup$
    – thils
    Commented Oct 5, 2015 at 6:35
1
$\begingroup$

enter image description here

Given and desired lists are:

Tl = {{a, 3, b}, {c, 6, d}, {e, 9, f}, {g, 5, h}};
lT = {{b, 5, a}, {d, 9, c}, {f, 6, e}, {h, 3, g}};

Rule @@ MatrixForm /@ {Tl, lT}

enter image description here

  1. The second column needs to be reversed (upside down).
  2. The first and the third column need to be interchanged.

Using SubsetMap:

SubsetMap[Reverse,
 SubsetMap[Reverse, #, {1, 3}] & /@ Tl
 , {All, 2}]

{{b, 5, a}, {d, 9, c}, {f, 6, e}, {h, 3, g}}

$\endgroup$
1
  • $\begingroup$ The Join variant similar to other answers would be: Transpose@Join[{Tl[[All, 3]]}, {Reverse@Tl[[All, 2]]}, {Tl[[All, 1]]}] $\endgroup$
    – Syed
    Commented Aug 26, 2023 at 10:03

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.