8
$\begingroup$

I have two matrices. They are,

m1={{a,b},{c,d}};
m2={{w,x},{y,z}};

I want to create a matrix of paired values that looks like this,

{{{a, w}, {b, x}}, {{c, y}, {d, z}}}

My equation for doing so looks like this,

Transpose /@ Transpose@{m1, m2}

and it works well; however, I thought I could use Map to accomplish the same thing at two different levels of the input. I have been unsuccessful in doing so. I have tried things like,

Map[Transpose, {m1, m2}, {0, 1}]

which results in,

{{{a, c}, {w, y}}, {{b, d}, {x, z}}}

which is clearly not what I want.

Is there a way to use Map in the above fashion and not call Transpose twice as I have done in the successful example?

P.S. I have seen this example; however, the output format is incorrect for what I want. Yes, you could recreate the matrix dimensions with Partition; however, I am looking for a more minimal expression.

Review of Answer Speeds

I reviewed the following answers for speed using Timing.

Timing[Flatten[{m1,m2},{{2},{3}}]]][[1]]
(* 0.000021 *)
Timing[Transpose[{m1,m2},{3,1,2}]][[1]]
(* 0.000038 *)
Timing[MapThread[List,{m1,m2},2]][[1]]
(* 8.*10^-6 *)
$\endgroup$
1
  • $\begingroup$ Thanks for the edits @xzczd. $\endgroup$ Commented Oct 11, 2022 at 21:45

7 Answers 7

13
$\begingroup$
MapThread[List, {m1, m2}, 2]

{{{a, w}, {b, x}}, {{c, y}, {d, z}}}

More alternatives that yield the same answer:

Table[Transpose@{m1[[i]], m2[[i]]}, {i, 1, Length[m1]}]
$\endgroup$
7
  • 1
    $\begingroup$ Works with ArrayReshape[List@Flatten[{m1, m2}, {{2, 3}}], Array[2 &, 3]]. $\endgroup$ Commented Oct 11, 2022 at 16:25
  • 1
    $\begingroup$ @xzczd thanks for spotting that. Not sure how I missed it :/ $\endgroup$
    – bmf
    Commented Oct 11, 2022 at 17:12
  • 1
    $\begingroup$ @E.Chan-López still in the process of...paperwork is killing me $\endgroup$
    – bmf
    Commented Oct 11, 2022 at 17:12
  • 1
    $\begingroup$ Thanks @bmf, I played with MapThread but did not use the List function and I ran into trouble with MapThread removing the Head. With Map, I tried keeping the Head using Head->True; however, that gave me strange results. I think your answer best responds to the spirit of my question. $\endgroup$ Commented Oct 11, 2022 at 21:28
  • 1
    $\begingroup$ @desla.slade glad I was able to help :) $\endgroup$
    – bmf
    Commented Oct 12, 2022 at 8:24
12
$\begingroup$

Since particular use of Transpose is shown, let me show the particular use of Flatten:

Flatten[{m1, m2}, {{2}, {3}}]

To learn more about this syntax, check this post.

$\endgroup$
1
  • $\begingroup$ I'd accept this answer too if I could accept multiple answers. $\endgroup$ Commented Oct 11, 2022 at 21:31
10
$\begingroup$

Easier than using Map is to just use the other form of Transpose:

Transpose[{m1, m2}, {3, 1, 2}]

If you really wanted to do a Map-ish thing, MapThread might be easier:

MapThread[Transpose@*List, {m1, m2}]
$\endgroup$
3
  • $\begingroup$ (+1) nice to see that particular use of Transpose $\endgroup$
    – bmf
    Commented Oct 11, 2022 at 16:10
  • $\begingroup$ Thanks @lericr. This is, I think, the most elegant answer. I played around with trying to move the different levels but my intuition for this is poor. $\endgroup$ Commented Oct 11, 2022 at 21:24
  • $\begingroup$ I'd accept this answer too if I could accept multiple answers. $\endgroup$ Commented Oct 11, 2022 at 21:31
10
$\begingroup$

As long as it is symbolic:

(m1 + m2) /. Plus -> List

Or its twin brother:

m1 m2 /. Times -> List

Result:

{{{a, w}, {b, x}}, {{c, y}, {d, z}}}

$\endgroup$
8
$\begingroup$

Just another way using Outer:

Table[Outer[List, m1, m2][[i, j, i, j]], {i, 1, 2}, {j, 1, 2}]
(*{{{a, w}, {b, x}}, {{c, y}, {d, z}}}*)
$\endgroup$
7
$\begingroup$

Riffing off of Syed's answer:

Function[{x, y}, {x, y}, Listable][m1, m2]

This started as

SetAttributes[f, Listable];
f[m1, m2] /. f -> List

Then I just turned it into an explicit function. This should avoid the problem Syed identified of needing to be symbolic.

EDIT

Okay, a bit more terse:

Function[, {##}, Listable][m1, m2]
$\endgroup$
1
  • $\begingroup$ (+1) Nice, Indeed! $\endgroup$ Commented Oct 11, 2022 at 22:45
1
$\begingroup$
m1 = {{a, b}, {c, d}};

m2 = {{w, x}, {y, z}};

Using MapApply (new in 13.1)

MapApply[List] /@ (m1 m2)

{{{a, w}, {b, x}}, {{c, y}, {d, z}}}

$\endgroup$

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.