16

I have two lists with equal length, and I want to exchange the elements on every even positions. For example,

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

will return

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

It has to be able to deal with length of both even and odd; and in the real case the list is very long. I am not satisfied with naive approaches with indexing and partitioning because they are slow. Is there any fast approaches?

vapor
  • 7,911
  • 2
  • 22
  • 55

6 Answers6

15
list[[All, 2 ;; ;; 2]] = Reverse @ list[[All, 2 ;; ;; 2]]; 
list
{{1, 7, 3, 9, 5}, {6, 2, 8, 4, 10}}

or list[[-1 ;; 1 ;; -1, 2 ;; ;; 2]].

ps. keep in mind that this changes list.

Mr.Wizard
  • 271,378
  • 34
  • 587
  • 1,371
Kuba
  • 136,707
  • 13
  • 279
  • 740
  • Thanks! Your solution is the fastest – vapor Aug 05 '16 at 09:42
  • 2
    I modified your code to use the backward-compatible form. I also find this more readable as one can get lost in all the semicolons. I hope you do not mind. – Mr.Wizard Aug 05 '16 at 11:49
  • 5
    You could also eliminate Reverse with: list[[All, 2 ;; ;; 2]] = list[[{2, 1}, 2 ;; ;; 2]];, or perhaps more explicitly list[[{1, 2}, 2 ;; ;; 2]] = list[[{2, 1}, 2 ;; ;; 2]]; – Mr.Wizard Aug 05 '16 at 11:56
5
ClearAll[f1]
f1 = Module[{l2 = Transpose@#}, l2 = Transpose[MapAt[Reverse, l2, {2 ;; ;; 2}]]] &;

f1@{{1, 2, 3, 4, 5}, {6, 7, 8, 9, 10}}

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

Or

ClearAll[f2]
f2 = Module[{l2 = #}, 
    l2[[All, 2 ;; ;; 2]] = Reverse /@ Transpose[l2[[All, 2 ;; ;; 2]]]; l2] &;

f2@{{1, 2, 3, 4, 5}, {6, 7, 8, 9, 10}}

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

kglr
  • 394,356
  • 18
  • 477
  • 896
  • I knew spanning specification worked with Take (was designed for?), but it obviously works with MapAt as well. But a span of elements is generally not equivalent to a list of positions, right? – BoLe Aug 05 '16 at 10:02
4

I think Reverse is better suited for long lists. When the lists that need be reversed have length 2, I would do this:

L = {{1, 2, 3, 4, 5}, {6, 7, 8, 9, 10}};
Transpose[MapAt[#[[{2, 1}]] &, Transpose[L], 2 ;; ;; 2]]
Coolwater
  • 20,257
  • 3
  • 35
  • 64
  • I knew spanning specification worked with Take (was designed for?), but it obviously works with MapAt as well. But a span of elements is generally not equivalent to a list of positions, right? – BoLe Aug 05 '16 at 10:03
2
lst = {{1, 2, 3, 4, 5}, {6, 7, 8, 9, 10}};
Module[{i = 1},
  Transpose@MapThread[If[EvenQ[i++], Reverse@{##}, {##}] &, lst]
 ]
(* {{1, 7, 3, 9, 5}, {6, 2, 8, 4, 10}} *)
march
  • 23,399
  • 2
  • 44
  • 100
0
list = {{1, 2, 3, 4, 5}, {6, 7, 8, 9, 10}};

Riffle @@ ReverseSortBy[Length] @
  Map[Lookup[#], GroupBy[OddQ] /@ list] & /@ {True, False}

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

eldo
  • 67,911
  • 5
  • 60
  • 168
0

Using SubsetMap:

Clear["Global`*"];

list = {Style[#, Red] & /@ {1, 2, 3, 4, 5, a, b, c}, Style[#, Blue] & /@ {6, 7, 8, 9, 10, d, e, f}}

enter image description here

(* select even positions *)

pos = Position[list, _, {2}, Heads -> False] // Select[EvenQ@*Last];

(* rotate according to the number of columns/2 floored to an integer *)

SubsetMap[ RotateLeft[#, Floor[(First@Dimensions@Last@list)/2]] &, list, pos]

enter image description here

Syed
  • 52,495
  • 4
  • 30
  • 85