# Fastest way : two by two list inversion

Consider a list of even length, for example list={1,2,3,4,5,6,7,8}

what is the fastest way to accomplish both these operations ?

Operation 1: two by two element inversion, the output is:

{2,1,4,3,6,5,8,7}


A code that work is:

Flatten@(Reverse@Partition[list,2])


Operation 2: Two by two Reverse, the output is:

{7,8,5,6,3,4,1,2}


A code that work is:

Flatten@(Reverse@Partition[Reverse[list],2])


The real lists have length 16, no need for anything adapated to long lists

• You want that to be done for many lists at once? Commented Mar 18, 2021 at 10:41
• Not necessarily, but I could tweak my code to make it so, so yes why not ! Commented Mar 18, 2021 at 10:44

We can achieve a speed up of approx. 2 by using Riffle:

list = {1, 2, 3, 4, 5, 6, 7, 8};

For the first problem:

Riffle[list[[2 ;; ;; 2]], list[[1 ;; ;; 2]]]


For the second problem:

Riffle[list[[-2 ;; 1 ;; -2]], list[[-1 ;; 2 ;; -2]]]


If you have the do that very often, store your lists in a packed matrix like a below (that's a good idea anyways!), use your current code to generate a permutation, and then use Part to apply the permutations on the columns of a

n = 16;
a = RandomInteger[{1, 100}, {1000000, n}];

p1 = Flatten@(Reverse@Partition[Range[n], 2]);
b1 = Map[Flatten@(Reverse@Partition[#, 2]) &, a]; // RepeatedTiming // First
c1 = a[[All, p1]]; // RepeatedTiming // First
b1 == c1

p2 = Flatten@(Reverse@Partition[Range[n, 1, -1], 2]);
b2 = Map[Flatten@(Reverse@Partition[Reverse[#], 2]) &, a]; // RepeatedTiming // First
c2 = a[[All, p2]]; // RepeatedTiming // First
b2 == c2


0.338

0.041

True

0.463

0.040

True

If you are still free to choose you data layout, then you may consider to store the lists in "structure of arrays" format (i.e., by using the transpose of a) in order to obtain a small percentage of extra performance:

aT = Transpose[a];
b1T = aT[[p1]]; // RepeatedTiming // First
b2T = aT[[p2]]; // RepeatedTiming // First

Transpose[b1] == b1T
Transpose[b2] == b2T


0.035

0.035

True

True

PermutationList[Cycles[Partition[list,2]]]

{2, 1, 4, 3, 6, 5, 8, 7}


Simply Reverse the output above to get your second list:

Reverse @ %

{7, 8, 5, 6, 3, 4, 1, 2}


Alternatively, define a Cycles object that can used to Permute other lists:

cycles = Cycles[Partition[Range @ 8, 2]];

Permute[list, cycles]

{2, 1, 4, 3, 6, 5, 8, 7}


or

 list[[PermutationList @ cycles]]

{2, 1, 4, 3, 6, 5, 8, 7}


Reverse the input list and Permute:

Permute[Reverse @ list,cycles]

{7, 8, 5, 6, 3, 4, 1, 2}

Permute[CharacterRange["A", "H"], cycles]

{"B", "A", "D", "C", "F", "E", "H", "G"}

Permute[Reverse @ CharacterRange["A", "H"], cycles]

{"G", "H", "E", "F", "C", "D", "A", "B"}

list = {1, 2, 3, 4, 5, 6, 7, 8};

SequenceCases[list, x : {_, _} :> Splice @ Reverse @ x]


{2, 1, 4, 3, 6, 5, 8, 7}

SequenceCases[Reverse @ list, x : {_, _} :> Splice @ Reverse @ x]


{7, 8, 5, 6, 3, 4, 1, 2}

Using Developer PartitionMap and Reverse:

list = {1, 2, 3, 4, 5, 6, 7, 8};

Reverse@DeveloperPartitionMap[Sequence @@ Reverse @@ {#} &, list, 2]

(*{7, 8, 5, 6, 3, 4, 1, 2}*)


Or, as @eldo points out, using BlockMap, as he also made use of BlockMap in the post-Reference:

Reverse@BlockMap[Sequence @@ Reverse@# &, list, 2]

(*{7, 8, 5, 6, 3, 4, 1, 2}*)

• Or BlockMap instead of Developer...
– eldo
Commented Dec 12, 2023 at 23:24
• That's right, @eldo, I remember you used BlockMap. Let me quote you. :-) Commented Dec 12, 2023 at 23:28

Using TakeList:

list = {1, 2, 3, 4, 5, 6, 7, 8}

sel = List /@ Flatten@Table[{2, 1}, Length@list/2];

TakeList[list, sel] // Flatten
`

{2, 1, 4, 3, 6, 5, 8, 7}