# Elementwise join

I have two tensors of arbitrary but equal rank n (and equal dimensions): A and B, and I want to get a third tensor of rank n + 1, C.

I want to do a element by element Join, so the element in A and the corresponding element in B are contracted into a list in C.

For example, with n = 2:

A = {{a[0,0],a[1,0]},{a[0,1],a[1,1]}};
B = {{b[0,0],b[1,0]},{b[0,1],b[1,1]}};


then:

C = {{ {a[0,0],b[0,0]} , {a[1,0],b[1,0]} },{ {a[0,1],b[0,1]} , {a[1,1],b[1,1]} }}


I think it might be doable with some combination of Inner and List, but I'm not sure.

-
 Note: C is a built-in symbol in System  and it's not wise to assign/modify it unless absolutely necessary. – rm -rf♦ Jan 7 at 23:19 Sorry, I was using A, B and C as example variables. – Andrew Spott Jan 7 at 23:20 This is very strongly related, although the way the two questions are worded, they're entirely different mathematica.stackexchange.com/q/17291/5 – rm -rf♦ Jan 7 at 23:35

Here are a couple of possibilities.

MapThread[Riffle[{#1}, {#2}] &, {aA, bB}, 2]

(* Out[64]= {{{a[0, 0], b[0, 0]}, {a[1, 0], b[1, 0]}}, {{a[0, 1],
b[0, 1]}, {a[1, 1], b[1, 1]}}} *)

Transpose[ArrayFlatten[{aA, bB}], {3, 1, 2}]

(* Out[72]= {{{a[0, 0], b[0, 0]}, {a[1, 0], b[1, 0]}}, {{a[0, 1],
b[0, 1]}, {a[1, 1], b[1, 1]}}} *)


Another that I like less:

Map[Thread, Thread[{aA, bB}]]


--- edit ---

Actually that second one should just be

Transpose[{aA, bB}, {3, 1, 2}]


The ArrayFlatten was not needed in this case (it can be useful somethimes though). And in case it was not clear, the lists are:

aA = {{a[0, 0], a[1, 0]}, {a[0, 1], a[1, 1]}};
bB = {{b[0, 0], b[1, 0]}, {b[0, 1], b[1, 1]}};


--- end edit ---

-

Here's a fairly simple way of doing it (ignore the front end's syntax warning):

Function[, {##}, Listable][A, B]
(* {{{a[0, 0], b[0, 0]}, {a[1, 0], b[1, 0]}},
{{a[0, 1],  b[0, 1]}, {a[1, 1], b[1, 1]}}} *)

-
Why does that work? It is very interesting, but what if I want to make a[0,0] a list as well? – Andrew Spott Jan 7 at 23:48
If you consider element-wise multiplication A B, that is possible because of the Listable attribute of Times. In other words, it threads over lists in its arguments. What I've done above is similar – it creates a pure function that "joins" the arguments ({#}) and threads it over lists (Listable). The omitted argument is taken as Null. I don't understand what you mean by wanting to make a[0,0] a list as well, as it's no longer element-wise join, as you wanted. – rm -rf Jan 7 at 23:55
+1. You are too fast, I am running out of tricks :-) – Leonid Shifrin Jan 8 at 0:01

Maybe a pedagogical alternative

(A + B) /. Plus -> List
`
-
I don't think this will work in general. Think about what happens if the elements of A and B are numbers. – m_goldberg Jan 8 at 1:05
sure. as mentioned: it is just pedagogical in that sense that it is easy to understand and you don't have to use Function with a Null argument. – Rolf Mertig Jan 8 at 9:34