4
$\begingroup$

I have two matrices M1 and M2. Both have same number of columns but different number of rows. I want to make a new matrix M which should have 1st row form M1, second row form M2, third row form M1, fourth row from m2 and so on. For example,

M1 = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
M2 = {{10, 11, 12}, {13, 14, 15}, {16, 17, 18}, {19, 20, 21}, {22, 23, 24}};

and my final matrix should be

M = {{1, 2, 3}, {10, 11, 12}, {4, 5, 6}, {13, 14, 15}, {7, 8, 9}, {16, 17, 18}, {19, 20, 21}, {22, 23, 24}};

Please note length of each matrix is over 1000. Thank you for your help.

$\endgroup$

2 Answers 2

8
$\begingroup$
Join @@ Flatten[{M1, M2}, {{2}, {1}}]
(* {{1, 2, 3}, {10, 11, 12}, {4, 5, 6}, {13, 14, 15}, {7, 8, 9}, {16, 17,
   18}, {19, 20, 21}, {22, 23, 24}} *)

Reference for using the second argument of Flatten to transpose a ragged array.


Update: even shorter (big praise to Flatten):

Flatten[{M1, M2}, {2, 1}]
$\endgroup$
5
  • 2
    $\begingroup$ +1 nice usage of Flatten! $\endgroup$
    – C. E.
    Aug 8, 2014 at 22:07
  • $\begingroup$ Thanks! I discovered it from a SE Q&A and I'm trying to dig it out to give proper credit. $\endgroup$
    – seismatica
    Aug 8, 2014 at 22:08
  • 2
    $\begingroup$ +1 One of the fastest answers ever given :) $\endgroup$
    – eldo
    Aug 8, 2014 at 22:09
  • 1
    $\begingroup$ @seismatica Thanks for quick reply. I verified your codes in my data. It works so well. Thank you so much. You saved my life! ::::)))) $\endgroup$
    – ramesh
    Aug 8, 2014 at 22:57
  • $\begingroup$ You're welcome! Glad it helped. $\endgroup$
    – seismatica
    Aug 8, 2014 at 22:58
2
$\begingroup$

Another method is with Riffle:

If[Length[M1] > Length[M2],
 Riffle[M1, M2, {2, 2 Length@M2, 2}],
 Riffle[M2, M1, {1, 2 Length@M1, 2}]
]

but the Flatten method is nicer, since it doesn't need the length-comparison logic.

Edited to reflect kguler's nice use of the third Riffle option.

$\endgroup$
5
  • $\begingroup$ Very nice use of Riffle! It seems that your code will duplicate the {16, 17, 18}. I think using [[Length[M1]+1 ;; -1]] will fix that. Also, I think you can just use Riffle[M1, M2, {2, -1, 2}] though your use of Riffle is perfectly fine as it is. $\endgroup$
    – seismatica
    Aug 8, 2014 at 23:13
  • 2
    $\begingroup$ (+1) You can also use the simpler Riffle[M2,M1,{1,2 Length@M1,2}] as the 3rd argument of If. $\endgroup$
    – kglr
    Aug 8, 2014 at 23:23
  • $\begingroup$ @seismatica, you need the Length in the third argument and not -1 because otherwise it will repeat. Try, for example, with M2 = {{10,11,12}}; $\endgroup$
    – evanb
    Aug 8, 2014 at 23:50
  • $\begingroup$ @evanb Then it would default to your True case of If. I don't think you have to worry (in your older code) about riffling the longer M2 into the shorter M1 in the False case, since M2 will not run out and repeat. I think your old code (with my -1) was If[Length[M1] > Length[M2], Riffle[M1, M2, {2, 2 Length[M2], 2}], Join[Riffle[M1, M2, {2, -1, 2}], M2[[Length[M1] + 1 ;; -1]]]] $\endgroup$
    – seismatica
    Aug 8, 2014 at 23:55
  • $\begingroup$ My comment for the -1 was only for the False case. I'm sorry I wasn't clear. You're right, you need {2, 2Length@M2, 2}] for the True case in the old code, otherwise M2 would repeat. However, this also means that you can use Riffle[M2, M1, {1, -1, 2}] for your True case in the new code using @Pickett's trick of Riffle at the first position. $\endgroup$
    – seismatica
    Aug 9, 2014 at 0:03

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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