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 these two lists, both with the same length in the first dimension:

l1={{a1,a2},{b1,b2},{c1,c2}};
l2={{{1,2,3},{4,5,6}},{{10,11,12},{13,14,15},{16,17,18}},{{19,20,21}}};

And I need mix both to get into this result:

{{a1,a2,1,2,3},{a1,a2,4,5,6},{b1,b2,10,11,12},{b1,b2,13,14,15},
{b1,b2,16,17,18},{c1,c2,19,20,21}}

I have done this code that do the job:

Flatten[MapThread[Function[{a,b},Join[a,#]&/@b][#1,#2]&,{l1,l2}],1]

But I think it could be simpler. Some clue?

share|improve this question
    
Thanks for the Accept. :-) –  Mr.Wizard Aug 29 '13 at 11:23
    
Short and fast is always the best. –  Murta Aug 29 '13 at 11:31
    
A lot of people don't bother to look at answers to old questions; I appreciate the fact that you do. –  Mr.Wizard Aug 29 '13 at 11:32
add comment

9 Answers 9

up vote 7 down vote accepted

I don't know why no one thought to use ArrayFlatten:

wizard1[l1_, l2_] := ArrayFlatten @ MapThread[Append, {l1, l2}]

wizard2[l1_, l2_] := ArrayFlatten @ Join[l1, List /@ l2, 2]

Test:

wizard1[l1, l2]

wizard1[l1, l2] === wizard2[l1, l2]
 {{a1, a2, 1, 2, 3}, {a1, a2, 4, 5, 6}, {b1, b2, 10, 11, 12},
  {b1, b2, 13, 14, 15}, {b1, b2, 16, 17, 18}, {c1, c2, 19, 20, 21}}

True

According to ssch's test suite these functions are also the fastest:

testSpeed[50000, 15]

enter image description here

share|improve this answer
add comment

A similar alternative

MapThread[Flatten /@ Tuples[{{#1}, #2}] &, {l1, l2}]~Flatten~1

{{a1, a2, 1, 2, 3}, {a1, a2, 4, 5, 6}, {b1, b2, 10, 11, 12}, {b1, b2, 13, 14, 15}, {b1, b2, 16, 17, 18}, {c1, c2, 19, 20, 21}}

share|improve this answer
    
Nice! I liked the way you use Tuples to distribute the elements. –  Murta Oct 28 '12 at 1:26
    
I little bit faster with Flatten[MapThread[Tuples[{{#1},#2}]&,{l1,l2}],{{1,2},{3,4}}] –  Murta Aug 29 '13 at 11:19
add comment

Your approach looks fine to me, but here's an alternative using Outer and Thread:

(Outer[Flatten[{##}] &, {#1}, #2, 1] & @@@ Thread[{l1, l2}]) ~Flatten~ 2
(* {{a1, a2, 1, 2, 3}, {a1, a2, 4, 5, 6}, {b1, b2, 10, 11, 12}, {b1, b2, 13, 14, 15}, 
    {b1, b2, 16, 17, 18}, {c1, c2, 19, 20, 21}} *)

You could also use Transpose[{l1,l2}] instead of thread (\[Transpose] looks compact in the front end).

share|improve this answer
add comment

Something a bit compact:

Flatten[MapThread[Join[ConstantArray[#1, Length[#2]], #2, 2] &, {l1, l2}], 1]
(* {{a1, a2, 1, 2, 3}, {a1, a2, 4, 5, 6}, {b1, b2, 10, 11, 12}, {b1, b2, 13, 14, 15},
    {b1, b2, 16, 17, 18}, {c1, c2, 19, 20, 21}} *)
share|improve this answer
add comment

Using combinations of Thread and Join:

Join @@@ Join @@ (Thread[#, List, {2}] & /@ Thread@{l1, l2})

or (... why not?)

Join @@@ Join @@ (Thread[{##}, List, {2}] & @@@ Thread@{l1, l2})

UPDATE: ... few more:

Using ArrayPad:

Join@@(ArrayPad[#[[1]], {{0}, {2, 0}}, #[[2]]] & /@ Thread[{l2,Reverse/@ l1}])

and variations with MapThread:

Join @@ MapThread[ArrayPad[#1, {{0}, {2, 0}}, #2] &, {l2, Reverse /@ l1}]

Join @@ MapThread[Function[{a, b}, Join[a, #] & /@ b], {l1, l2}]

Join @@ MapThread[Function[e, Join[#1, e]] /@ #2 &, {l1, l2}]
share|improve this answer
    
I was about to give it a try when I noticed that your answer's better than mine in every single way. –  VF1 Nov 7 '12 at 4:40
    
@VF1, thank you... you might like the updated version with 9 @s :) –  kguler Nov 7 '12 at 7:47
    
+1 Excellent idea with the ArrayPad. –  Sasha Nov 7 '12 at 16:30
    
@Sasha, thank you. –  kguler Nov 8 '12 at 1:45
add comment

I did some speed comparisons on the different solutions

murta[l1_, l2_] := 
  Flatten[MapThread[
    Function[{a, b}, Join[a, #] & /@ b][#1, #2] &, {l1, l2}], 1];
rojo[l1_, l2_] := 
  MapThread[Flatten /@ Tuples[{{#1}, #2}] &, {l1, l2}]~Flatten~1;
jm[l1_, l2_] := 
  Flatten[MapThread[
    Join[ConstantArray[#1, Length[#2]], #2, 2] &, {l1, l2}], 1];
rmrf[l1_, 
   l2_] := (Outer[Flatten[{##}] &, {#1}, #2, 1] & @@@ 
     Thread[{l1, l2}])~Flatten~2;
mike[l1_, l2_] := 
  DeleteCases[Flatten[Join[{#, #, #} & /@ l1, l2, 3], 1], {_, _}];
istván1[l1_, l2_] := 
  Flatten[Thread[f[l1, l2]] /. f[a_, b_] :> (Join[a, #] & /@ b), 1];
istván2[l1_, l2_] := 
  Flatten[MapThread[
    PadLeft[#1, {Length@#1, 5}, #2] &, {l2, Reverse /@ l1}], 1];
imagedr[l1_, l2_] := 
  Flatten[Thread[
      Join @@ {#[[1]], #[[2]]\[Transpose]}] & /@ ({l1, 
       l2}\[Transpose]), 1];
kguler1[l1_, l2_] := 
  Join @@@ Join @@ (Thread[#, List, {2}] & /@ Thread@{l1, l2});
kguler2[l1_, l2_] := 
  Join @@@ Join @@ (Thread[{##}, List, {2}] & @@@ Thread@{l1, l2});
kguler3[l1_, l2_] := 
  Join @@ (ArrayPad[#[[1]], {{0}, {2, 0}}, #[[2]]] & /@ 
     Thread[{l2, Reverse /@ l1}]);
kguler4[l1_, l2_] := 
  Join @@ MapThread[
    ArrayPad[#1, {{0}, {2, 0}}, #2] &, {l2, Reverse /@ l1}];
kguler5[l1_, l2_] := 
  Join @@ MapThread[Function[{a, b}, Join[a, #] & /@ b], {l1, l2}];
kguler6[l1_, l2_] := 
  Join @@ MapThread[Function[e, Join[#1, e]] /@ #2 &, {l1, l2}];

mthds = {murta, rojo, jm, rmrf, mike, istván1, istván2, imagedr, 
   kguler1, kguler2, kguler3, kguler4, kguler5, kguler6};
testSpeed[n_, m_] := Module[{l1, l2},
  l1 = RandomReal[{0, 1}, {n, 2}];
  l2 = Table[RandomReal[{0, 1}, {RandomInteger[{1, m}], 3}], {n}];
  Sort[Map[
     {ToString[#], First[AbsoluteTiming[#[l1, l2]]]} &, mthds], 
    Last[#1] < Last[#2] &] // TableForm
  ]

First test, both lists length 5000, second one has at most 5 lists to append:

testSpeed[5000, 5]
kguler4 0.035028
mike    0.040346
istván2 0.042375
jm  0.044726
kguler3 0.044926
istván1 0.054379
kguler5 0.059240
kguler1 0.060311
kguler2 0.062870
murta   0.065296
kguler6 0.065683
imagedr 0.080554
rmrf    0.102988
rojo    0.116306

With up to 50 sublists:

testSpeed[5000, 50]
kguler4 0.051828
kguler3 0.059161
jm  0.100330
istván2 0.102177
imagedr 0.139533
mike    0.188815
istván1 0.268590
kguler5 0.270507
murta   0.285236
kguler6 0.343441
kguler2 0.365733
kguler1 0.367342
rojo    0.595591
rmrf    0.684573

So I'd go with kgulers solution:

Join @@ MapThread[
    ArrayPad[#1, {{0}, {2, 0}}, #2] &, {l2, Reverse /@ l1}]
share|improve this answer
add comment

You're joining columns at the 3rd level but have ragged lists:

DeleteCases[Flatten[Join[{#, #, #} &/@l1, l2, 3], 1], {_, _}]

(* {{a1, a2, 1, 2, 3}, {a1, a2, 4, 5, 6}, {b1, b2, 10, 11, 12}, {b1, b2, 
  13, 14, 15}, {b1, b2, 16, 17, 18}, {c1, c2, 19, 20, 21}} *)

(Joining ragged lists gives you an non-ragged list with padding that has to be removed with DeleteCases otherwise this could be concise)

share|improve this answer
add comment

A variant using Thread and Transpose

Flatten[Thread[Join @@ {#[[1]], #[[2]]\[Transpose]}] & /@ ({l1, l2}\[Transpose]),1]

{{a1, a2, 1, 2, 3}, {a1, a2, 4, 5, 6}, {b1, b2, 10, 11, 12}, {b1, b2, 13, 14, 15}, {b1, b2, 16, 17, 18}, {c1, c2, 19, 20, 21}}

share|improve this answer
add comment

One more with Thread and Map:

Flatten[Thread[f[l1, l2]] /. f[a_, b_] :> (Join[a, #] & /@ b), 1]

And one with PadLeft:

Flatten[MapThread[PadLeft[#1, {Length@#1, 5}, #2] &, {l2, Reverse /@ l1}], 1]

I wonder whether we can abuse Partition's padding capabilities (or even Riffle's)...

share|improve this answer
add comment

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.