14
$\begingroup$

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}]
$\endgroup$

12 Answers 12

10
$\begingroup$

How about this

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

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

$\endgroup$
9
$\begingroup$

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.)

$\endgroup$
  • $\begingroup$ Whats the -2 doing in this case? $\endgroup$ – Gordon Coale Sep 26 '14 at 10:30
  • $\begingroup$ @GordonCoale ref/Apply, Details and Options: "A negative level -n consists of all parts of expr with depth n." See ref/Depth for more explanation. $\endgroup$ – William Sep 26 '14 at 14:41
8
$\begingroup$

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}} *)
$\endgroup$
  • 1
    $\begingroup$ I think the output OP asking for is {a,d,g,{b,c,e,f,h,i}} (Why he accepted this 囧 ?) $\endgroup$ – xzczd Sep 27 '14 at 4:44
6
$\begingroup$
♯ = {## & @@ #, ## & @@@ #2} & @@ ({##}) & ;

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

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

$\endgroup$
  • $\begingroup$ Look, Ma! No letters! +1. You could even replace m with \[FivePointedStar]. $\endgroup$ – Michael E2 Sep 26 '14 at 17:51
  • $\begingroup$ thank you @Michael; updated with something along those lines. $\endgroup$ – kglr Sep 26 '14 at 18:07
  • $\begingroup$ This is evil. I approve. $\endgroup$ – Mr.Wizard Sep 26 '14 at 21:52
  • 1
    $\begingroup$ (1137) $\endgroup$ – Mr.Wizard Sep 26 '14 at 22:02
  • 1
    $\begingroup$ Yep, I can imagine in a near future #~♯~# == 42. @Mr.Wizard remember to give attribution. $\endgroup$ – Dr. belisarius Sep 27 '14 at 5:20
5
$\begingroup$

My take:

MapAt[Sequence @@ # &, Transpose[{l1, l2, l3}], {{1}, {2, All}}]
{a, d, g, {b, c, e, f, h, i}}
$\endgroup$
4
$\begingroup$

This is another way:

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

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

$\endgroup$
4
$\begingroup$

One option:

l1 + l2 + l3 /. Plus -> Sequence

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

$\endgroup$
  • 1
    $\begingroup$ @Mr.Wizard Tks!.. Now I have a nice one. $\endgroup$ – Murta Sep 26 '14 at 22:04
  • $\begingroup$ 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 $\endgroup$ – Mr.Wizard Sep 26 '14 at 22:16
  • $\begingroup$ Similar but more abusive: Re[l1, l2, l3] /. Re@x__ :> x $\endgroup$ – Mr.Wizard Sep 26 '14 at 22:19
  • $\begingroup$ 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}}. $\endgroup$ – xzczd Sep 27 '14 at 4:50
3
$\begingroup$

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)

$\endgroup$
  • $\begingroup$ +1 But can't help frowning while shaking my head :) $\endgroup$ – Dr. belisarius Sep 26 '14 at 15:01
2
$\begingroup$

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}}

$\endgroup$
  • 1
    $\begingroup$ Ha! I was tempted too :) $\endgroup$ – Dr. belisarius Sep 25 '14 at 23:03
2
$\begingroup$

Another solution :

Join[#[[1]], {#[[2]]}] &@(Flatten /@ Transpose@{l1, l2, l3})
(* {a, d, g, {b, c, e, f, h, i}} *)
$\endgroup$
2
$\begingroup$

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}}

$\endgroup$
  • $\begingroup$ The desired output is {a, d, g, {b, c, e, f, h, i}} :D $\endgroup$ – Dr. belisarius Sep 25 '14 at 23:02
1
$\begingroup$

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}}*)
$\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.