15
$\begingroup$

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?

$\endgroup$
13
$\begingroup$
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.

$\endgroup$
  • $\begingroup$ Thanks! Your solution is the fastest $\endgroup$ – happy fish Aug 5 '16 at 9:42
  • 2
    $\begingroup$ 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. $\endgroup$ – Mr.Wizard Aug 5 '16 at 11:49
  • 5
    $\begingroup$ 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]]; $\endgroup$ – Mr.Wizard Aug 5 '16 at 11:56
5
$\begingroup$
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}}

$\endgroup$
  • $\begingroup$ 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? $\endgroup$ – BoLe Aug 5 '16 at 10:02
4
$\begingroup$

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]]
$\endgroup$
  • $\begingroup$ 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? $\endgroup$ – BoLe Aug 5 '16 at 10:03
2
$\begingroup$
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}} *)
$\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.