8

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 *)

6 Answers6

12
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]}]
bmf
  • 15,157
  • 2
  • 26
  • 63
  • 1
    Works with ArrayReshape[List@Flatten[{m1, m2}, {{2, 3}}], Array[2 &, 3]]. – E. Chan-López Oct 11 '22 at 16:25
  • Hi, @bmf, I hope your move went well. Greetings. – E. Chan-López Oct 11 '22 at 16:27
  • 1
    @xzczd thanks for spotting that. Not sure how I missed it :/ – bmf Oct 11 '22 at 17:12
  • 1
    @E.Chan-López still in the process of...paperwork is killing me – bmf Oct 11 '22 at 17:12
  • 1
    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. – desla.slade Oct 11 '22 at 21:28
  • 1
    @desla.slade glad I was able to help :) – bmf Oct 12 '22 at 08:24
  • @bmf I have a doubt regarding the construction of certain types of pure functions. I asked a question in the community, in case you have any ideas about it. Greetings. – E. Chan-López Oct 13 '22 at 03:02
11

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.

xzczd
  • 65,995
  • 9
  • 163
  • 468
10

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}}}

Syed
  • 52,495
  • 4
  • 30
  • 85
9

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}]
lericr
  • 27,668
  • 1
  • 18
  • 64
7

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}}}*)
E. Chan-López
  • 23,117
  • 3
  • 21
  • 44
7

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]
lericr
  • 27,668
  • 1
  • 18
  • 64