6
$\begingroup$

Consider if I have some matrices constructed as such:

A = {
  { {} , {} },
  { {} , {} }
    }
B = {
  { a , b },
  { c , d }
    }
C = {
  { e , f },
  { g , h }
    }
...

A serves as a matrix of empty lists. I want to be able to append B, C, etc. to A, to obtain a final matrix like

A = {
  { {a, e, ...} , {b, f, ...} },
  { {c, g, ...} , {d, h, ...} }
    }

How can I do this? My matrices are always square and of the same dimensions. An alternative which could also be useful is to Join two matrices element by element, if the matrix elements of both are already lists.

$\endgroup$
6
  • $\begingroup$ You wrote "My matrices are always square and of the same dimensions". That is not true. Try Dimensions/@{A,B} $\endgroup$
    – Fortsaint
    Commented Jun 21, 2019 at 20:47
  • $\begingroup$ Kai, with A and B as inputs what is the desired result: {{{a}, {b}}, {{c}, {d}}} or {{{{}, a}, {{}, b}}, {{{}, c}, {{}, d}}}? $\endgroup$
    – kglr
    Commented Jun 22, 2019 at 0:45
  • $\begingroup$ @Fortsaint my meaning is that the matrices which are being appended are always the same dimension. Matrix A is simply a matrix of empty lists to append to. $\endgroup$
    – Kai
    Commented Jun 22, 2019 at 2:20
  • $\begingroup$ @kglr see the update $\endgroup$
    – Kai
    Commented Jun 22, 2019 at 2:22
  • $\begingroup$ with A = {{{}, {}}, {{}, {}}};B = {{a, b}, {c, d}};cc = {{e, f}, {g, h}}; if you use Transpose[{A, B, cc}, {3, 1, 2}] you get {{{{}, a, e}, {{}, b, f}}, {{{}, c, g}, {{}, d, h}}}. But your post says you want {{{a, e}, {b, f}}, {{c, g}, {d, h}}}, no? $\endgroup$
    – kglr
    Commented Jun 22, 2019 at 3:10

3 Answers 3

7
$\begingroup$

Suppose you have 4 matrices:

SeedRandom[1]
{a, b, c, d} = RandomInteger[1, {4, 2, 2}];

Then, you can use Transpose to construct the desired matrix:

Transpose[{a, b, c, d}, {3, 1, 2}]

{{{1, 0, 0, 0}, {1, 0, 1, 0}}, {{0, 0, 0, 0}, {1, 1, 0, 0}}}

$\endgroup$
3
  • 1
    $\begingroup$ I think Transpose[{a, b, c, d}, {3, 1, 2}] may be enough. $\endgroup$
    – Roman
    Commented Jun 21, 2019 at 23:14
  • $\begingroup$ @Roman Thanks, much simpler! $\endgroup$
    – Carl Woll
    Commented Jun 21, 2019 at 23:23
  • $\begingroup$ I'm still wrapping my head around the second argument of transpose, but this looks like the simplest way for me to achieve what I want. $\endgroup$
    – Kai
    Commented Jun 22, 2019 at 2:24
7
$\begingroup$

To join nested arrays elementwise, use the third argument of Join. For matrices, depth 1 (default) is rows, 2 is columns, and 3 is elements.

a = Array[{}&, {2,2}];

b = {
{b1, b2},
{b3, b4}
};

listEach = Map[List, #, {2}]&

appendEach[x_,y_] := Join[x, listEach[y], 3]

Print[appendEach[appendEach[a, b], b+5]]
(* {{{b1, 5 + b1}, {b2, 5 + b2}}, {{b3, 5 + b3}, {b4, 5 + b4}}} *)

Try it online!

However, if you are appending many matrices it may be more efficient to create a list of matrices using Sow / Reap, then Transpose into a matrix of lists.

$\endgroup$
6
  • $\begingroup$ What is the function of the & in the first line? $\endgroup$
    – Kai
    Commented Jun 22, 2019 at 2:26
  • $\begingroup$ It's the syntax for a pure function. $\endgroup$
    – lirtosiast
    Commented Jun 22, 2019 at 6:34
  • $\begingroup$ right but there's no argument so I'm confused what it does $\endgroup$
    – Kai
    Commented Jun 22, 2019 at 19:26
  • $\begingroup$ {}& takes no arguments and returns an empty list. The & is there because Array needs to be passed a function. $\endgroup$
    – lirtosiast
    Commented Jun 22, 2019 at 20:39
  • $\begingroup$ I see, this is the equivalent of ConstantArray[{},{2,2}] then? $\endgroup$
    – Kai
    Commented Jun 23, 2019 at 4:40
7
$\begingroup$

Update:

ClearAll[f1, f2]
f1 = MapThread[List, #, 2] &;
f2 = Flatten[#, {{2}, {3}}] &;

Using Carl's example setup:

SeedRandom[1]
{a, b, c, d} = RandomInteger[1, {4, 2, 2}];

f1[{a, b, c, d}]

{{{1, 0, 0, 0}, {1, 0, 1, 0}}, {{0, 0, 0, 0}, {1, 1, 0, 0}}}

f2[{a, b, c, d}] == f1[{a, b, c, d}] == Transpose[{a, b, c, d}, {3, 1, 2}]

True

If some input matrices might have {} as an element all methods above retain {}s in the combined matrix:

f1[{a, A, c, d}]

{{{1, {}, 0, 0}, {1, {}, 1, 0}}, {{0, {}, 0, 0}, {1, {}, 0, 0}}}

MapThread with Flatten[{##}] & as the first argument eliminates {}s:

MapThread[Flatten[{##}] &, {a, A, c, d}, 2] 

{{{1, 0, 0}, {1, 1, 0}}, {{0, 0, 0}, {1, 0, 0}}}

Original answer:

MapThread Flatten at Level 2:

MapThread[Flatten[{##}] &, {A, B}, 2]

{{{a}, {b}}, {{c}, {d}}}

$\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.