14

Is there a way of smarter way of joining list of the form

l1 = {a,{b,c}};
l2 = {d,{e,f}};
l3 = {g,{h,i}};

To obtain

{a,d,g,{b,c,e,f,h,i}}

The code I have is

 {Sequence @@ #1, Flatten[#2]} & @@  Transpose[{l1, l2, l3}]
mete
  • 1,188
  • 5
  • 16

12 Answers12

10

How about this

MapThread[Join, {l1, l2, l3}] /. Join -> Sequence

{a, d, g, {b, c, e, f, h, i}}

Junho Lee
  • 5,155
  • 1
  • 15
  • 33
9

This seems like a good way:

l1 = {a, {b, c}};
l2 = {d, {e, f}};
l3 = {g, {h, i}};

Apply[Sequence, Thread@{l1, l2, l3}, {-2}]

(* Out: {a, d, g, {b, c, e, f, h, i}} *)

It's been a few days, but I got distracted this morning from work and revisited this... My reward was seeing poetry (+1 btw), but I also killed a couple minutes running some timings on a sampling of the various answers:

ClearAll@t;
SetAttributes[t, HoldFirst];
t[e_, n_] := First@AbsoluteTiming[Do[e, {n}];]

OP:

t[
 {Sequence @@ #1, Flatten[#2]} & @@ Transpose[{l1, l2, l3}],
 10^6
 ]

(* Out: 3.849385 *)

This answer:

t[
 Apply[Sequence, Thread@{l1, l2, l3}, {-2}],
 10^6
 ]

(* Out: 2.882288 *)

Snapshot of a few other answers:

t[
 MapThread[Join, {l1, l2, l3}] /. Join -> Sequence,
 10^6
 ]

(* Out: 5.532553 *)

t[
 MapAt[Sequence @@ # &, Transpose[{l1, l2, l3}], {{1}, {2, All}}],
 10^6
 ]

(* Out: 6.293629 *)

t[
 FlattenAt[Flatten /@ Transpose[{l1, l2, l3}], 1],
 10^6
 ]

(* Out: 3.969397*)

(Performance of this operation is probably irrelevant for the OP's purposes, but I always enjoy playing on the performance side of things.)

William
  • 1,103
  • 6
  • 10
8

I don't know if this is "smarter". Anyway:

ClearAll@k; SetAttributes[k, Listable];
k @@ {l1, l2, l3} /. k -> Sequence
(* {a, d, g, {b, e, h, c, f, i}} *)
Dr. belisarius
  • 115,881
  • 13
  • 203
  • 453
  • 1
    I think the output OP asking for is {a,d,g,{b,c,e,f,h,i}} (Why he accepted this 囧 ?) – xzczd Sep 27 '14 at 04:44
6
♯ = {## & @@ #, ## & @@@ #2} & @@ ({##}) & ;

♯[l1, l2, l3]
(* {a, d, g, {b, c, e, f, h, i}} *)

See also: ♭ = ## & @@@ (## & @@@ {## & @@@ # & /@ #} & /@ #) &

kglr
  • 394,356
  • 18
  • 477
  • 896
5

My take:

MapAt[Sequence @@ # &, Transpose[{l1, l2, l3}], {{1}, {2, All}}]
{a, d, g, {b, c, e, f, h, i}}
RunnyKine
  • 33,088
  • 3
  • 109
  • 176
4

This is another way:

FlattenAt[Flatten /@ Transpose[{l1, l2, l3}], 1]

{a, d, g, {b, c, e, f, h, i}}

smayhem
  • 325
  • 1
  • 8
4

One option:

l1 + l2 + l3 /. Plus -> Sequence

{a, d, g, {b, c, e, f, h, i}}

Murta
  • 26,275
  • 6
  • 76
  • 166
  • 1
    @Mr.Wizard Tks!.. Now I have a nice one. – Murta Sep 26 '14 at 22:04
  • Indeed you do. Probably not as general as would be best, but then again neither are several other answers, and the OP never really specified the problem. +1 – Mr.Wizard Sep 26 '14 at 22:16
  • Similar but more abusive: Re[l1, l2, l3] /. Re@x__ :> x – Mr.Wizard Sep 26 '14 at 22:19
  • This answer has the same spirit as belisarius's, so does the output: it outputs {a, d, g, {b, e, h, c, f, i}} rather than {a, d, g, {b, c, e, f, h, i}}. – xzczd Sep 27 '14 at 04:50
3

Two very intuitive ways. First the Flattinator:

#2[#1[#1 /@ #1[{##3}, {2}], {1}], 1] &[Flatten, FlattenAt, l1, l2, l3]

and here the Padding-Miss-User

PadLeft[{Flatten[#2]}, 4, RotateLeft[#1]] & @@ Transpose[{l1, l2, l3}]

(Please don't use them. Just look and shake your head)

halirutan
  • 112,764
  • 7
  • 263
  • 474
2

Update

Transpose @ {l1, l2, l3} /. a:{__Symbol} :> Sequence @@ a

{a, d, g, {b, c, e, f, h, i}}

Original answer:

Append[First /@ #, Flatten[Last /@ #]] & [{l1, l2, l3}]

{a, d, g, {b, c, e, f, h, i}}

eldo
  • 67,911
  • 5
  • 60
  • 168
2

Rule based alternatives for completeness sake:

{l1, l2, l3} //. {{a__, {b__}}, {c_, {d__}}, 
    rest : {_, {__}} ...} :> {{a, c, {b, d}}, rest} // First

{a, d, g, {b, c, e, f, h, i}}

And:

Flatten[{l1, l2, l3}, {2, 1}] /. {start__, rest : {_, _} ...} :> {start, Join[rest]}

{a, d, g, {b, c, e, f, h, i}}

C. E.
  • 70,533
  • 6
  • 140
  • 264
2

Another solution :

Join[#[[1]], {#[[2]]}] &@(Flatten /@ Transpose@{l1, l2, l3})
(* {a, d, g, {b, c, e, f, h, i}} *)
qwerty
  • 1,199
  • 1
  • 7
  • 7
1

I would just add something for general case:

l1 = {a, h, u, {b, t, c}};
l2 = {d, e, t, y, {e, f}};
l3 = {g, {h, i}};

Append @@ ({Cases[#, _?(Head[#] =!= List &)], 
     Flatten[Cases[#, _List]]} &[Flatten[{l1, l2, l3}, 1]])

(*{a, h, u, d, e, t, y, g, {b, t, c, e, f, h, i}}*)
Basheer Algohi
  • 19,917
  • 1
  • 31
  • 78