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$
  • $\begingroup$ You wrote "My matrices are always square and of the same dimensions". That is not true. Try Dimensions/@{A,B} $\endgroup$ – Fortsaint Jun 21 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 Jun 22 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 Jun 22 at 2:20
  • $\begingroup$ @kglr see the update $\endgroup$ – Kai Jun 22 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 Jun 22 at 3:10
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$
  • $\begingroup$ I think Transpose[{a, b, c, d}, {3, 1, 2}] may be enough. $\endgroup$ – Roman Jun 21 at 23:14
  • $\begingroup$ @Roman Thanks, much simpler! $\endgroup$ – Carl Woll Jun 21 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 Jun 22 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$
  • $\begingroup$ What is the function of the & in the first line? $\endgroup$ – Kai Jun 22 at 2:26
  • $\begingroup$ It's the syntax for a pure function. $\endgroup$ – lirtosiast Jun 22 at 6:34
  • $\begingroup$ right but there's no argument so I'm confused what it does $\endgroup$ – Kai Jun 22 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 Jun 22 at 20:39
  • $\begingroup$ I see, this is the equivalent of ConstantArray[{},{2,2}] then? $\endgroup$ – Kai Jun 23 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, privacy policy and cookie policy

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