Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

I have two matrices $A$ and $B$ which are the same size. Each element of $A$ is a list of numbers. Each element of $B$ is just a number. How do I insert each element of $B$ into the corresponding list of $A$?

For example say I have:

A = {{{1,2},{3,4}},{{5,6},{7,8}},{{9,10},{11,12}}}

$ = \begin{pmatrix} (1,2) & (3,4)\\ (5,6) & (7,8) \\ (9,10) & (11,12) \end{pmatrix}$

and

B = {{0,0},{1,1},{2,2}}

$=\begin{pmatrix} 0 & 0\\1&1\\2&2 \end{pmatrix}$

How do I form:

{{{1,2,0},{3,4,0}},{{5,6,1},{7,8,1}},{{9,10,2},{11,12,2}}}

$ = \begin{pmatrix} (1,2,0) & (3,4,0)\\ (5,6,1) & (7,8,1) \\ (9,10,2) & (11,12,2) \end{pmatrix}$

Thanks very much for any help

share|improve this question
    
Are the columns of B always identical as shown in this example? –  Mr.Wizard Jun 24 at 18:24
    
No, just giving a simple example so I can understand. :) –  TomJS Jun 24 at 18:48

6 Answers 6

up vote 7 down vote accepted
f = Module[{tmp = ConstantArray[0, Dimensions[#1] + {0, 0, 1}]}, 
            tmp[[All, All, ;; -2]] = #1; tmp[[All, All, -1]] = #2; tmp] &;
f[a, b]
(* {{{1, 2, 0}, {3, 4, 0}},
    {{5, 6, 1}, {7, 8, 1}}, 
    {{9, 10, 2}, {11, 12, 2}}}*)

All methods posted so far:

f1 = MapThread[Append, {#1, #2}, 2] &;
f2 = Join[#1, Transpose[{#2}, {3, 1, 2}], 3] &;
f3 = MapThread[{Sequence @@ #1, #2} &, {#1, #2}, 2] &;
f4 = MapThread[Flatten[{##}] &, {#1, #2}, 2] &;
f5 = MapThread[Insert[#1, #2, -1] &, {#1, #2}, 2] &;
f6 = MapThread[Join[#1, {#2}] &, {#1, #2}, 2] &;
f7 = Partition[MapThread[Append, {Flatten[#1, 1], #2 // Flatten}], 2] &;
f8 = Join[#1, Map[List, #2, {-1}], 3] &;
f9 = Module[{tmp = ConstantArray[0, Dimensions[#1] + {0, 0, 1}]}, 
            tmp[[All, All, ;; -2]] = #1; tmp[[All, All, -1]] = #2; tmp] &;

Timings and ByteCounts using Mr.W's test setup:

A = RandomInteger[99, {700, 400, 200}];
B = RandomInteger[99, {700, 400}];
Grid[Prepend[Timing@ByteCount@#[A, B], #] & /@ 
    {f1, f2, f3, f4, f5, f6, f7, f8, f9}, Dividers -> All]~Style~24 (* thanks: Mr.W *)

enter image description here

share|improve this answer
    
+1 for timings. Regarding the update, why not Sequence @@ Timing @ ByteCount @ #[A, B]? Shorter and clearer IMO. –  Mr.Wizard Jun 24 at 22:22
    
Thank you @Mr.W (you should have seen the first version of Grid[...]:)) –  kguler Jun 24 at 22:25
    
Hey look, you picked up the Accept. Since you're open to suggestion how about: Grid[Prepend[Timing @ ByteCount @ #[A, B], #] & /@ {f1, f2, f3, f4, f5, f6, f7, f8, f9}, Dividers -> All] ~Style~ 24 –  Mr.Wizard Jun 24 at 22:32
    
Thank you againm @Mr.W. Accept is likely to be a mistake -- soon to be corrected now that timings table, with larger fonts, is more readable:) Thomas, thank you .. but are you sure?:) –  kguler Jun 24 at 22:50
    
Well it contains the most information for future readers. –  TomJS Jun 28 at 10:03
MapThread[Append, {A, B}, 2] // MatrixForm

enter image description here

share|improve this answer
    
+1... what sort of code is your email addr expressed in? –  alancalvitti Jun 24 at 14:16
    
@alancalvitti brainf*ck :D. Interpreter / generator. –  mfvonh Jun 24 at 14:18
    
That's the ticket. Thank you user mfvonh. –  TomJS Jun 24 at 14:21

just a nonpractical variation:

Join[A, Map[List, B, {-1}], 3]
share|improve this answer
    
+1 for using Join. Actually, this too will preserve packed arrays as above the "MapCompileLength" it will compile. Would you prefer that I delete my answer and include the examples in yours instead? (Though Transpose is still faster I believe.) –  Mr.Wizard Jun 24 at 18:37
    
@Mr.Wizard Please do not delete your answer :) Let both of them stay, if not then yours is more valuable :) –  Kuba Jun 24 at 18:49

Here are some more ways to do what is asked

a = {{{1, 2}, {3, 4}}, {{5, 6}, {7, 8}}, {{9, 10}, {11, 12}}};
b = {{0, 0}, {1, 1}, {2, 2}};

MapThread[{Sequence @@ #1, #2} &, {a, b}, 2]

MapThread[Flatten[{##}] &, {a, b}, 2]

MapThread[Insert[#1, #2, -1] &, {a, b}, 2]

MapThread[Join[#1, {#2}] &, {a, b}, 2]

and finally, using argument destructuring,

Block[{f},
 f[{x_, y_}, z_] := {x, y, z};
 MapThread[f, {a, b}, 2]]

All of the above return

{{{1, 2, 0}, {3, 4, 0}}, {{5, 6, 1}, {7, 8, 1}}, {{9, 10, 2}, {11, 12, 2}}}

The common thread (pun intended) running through all these examples is that any function accepting a 1st arg matching {x_, y_} and a 2nd arg matching z_ and producing {x, y, z} can be MapThread-ed at level 2 to produce the required result.

share|improve this answer

Unlike other answers here the combination of Join and Transpose will preserve a fully packed array:

<< Developer`

A = {{{1, 2}, {3, 4}}, {{5, 6}, {7, 8}}, {{9, 10}, {11, 12}}} // ToPackedArray;
B = {{0, 0}, {1, 1}, {2, 2}} // ToPackedArray;

Join[A, Transpose[{B}, {3, 1, 2}], 3] // PackedArrayQ
True

This allows superior speed and memory management:

A = RandomInteger[99, {700, 400, 200}];
B = RandomInteger[99, {700, 400}];

MapThread[Append, {A, B}, 2]          // ByteCount // Timing
Join[A, Transpose[{B}, {3, 1, 2}], 3] // ByteCount // Timing
{0.436, 262108032}

{0.0393, 225120132}

Edit: Kuba's method will also preserve a packed array when given input large enough to invoke compilation according to the value defined in SystemOptions["CompileOptions" -> "MapCompileLength"].

share|improve this answer

One solution could be like this:

Partition[MapThread[Append, {Flatten[A, 1], B // Flatten}], 2]
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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