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$
0

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$
2
  • $\begingroup$ Whats the -2 doing in this case? $\endgroup$ Sep 26, 2014 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, 2014 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
  • 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, 2014 at 4:44
6
$\begingroup$
♯ = {## & @@ #, ## & @@@ #2} & @@ ({##}) & ;

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

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

$\endgroup$
8
  • $\begingroup$ Look, Ma! No letters! +1. You could even replace m with \[FivePointedStar]. $\endgroup$
    – Michael E2
    Sep 26, 2014 at 17:51
  • $\begingroup$ thank you @Michael; updated with something along those lines. $\endgroup$
    – kglr
    Sep 26, 2014 at 18:07
  • $\begingroup$ This is evil. I approve. $\endgroup$
    – Mr.Wizard
    Sep 26, 2014 at 21:52
  • 1
    $\begingroup$ (1137) $\endgroup$
    – Mr.Wizard
    Sep 26, 2014 at 22:02
  • 1
    $\begingroup$ Yep, I can imagine in a near future #~♯~# == 42. @Mr.Wizard remember to give attribution. $\endgroup$ Sep 27, 2014 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$
4
  • 1
    $\begingroup$ @Mr.Wizard Tks!.. Now I have a nice one. $\endgroup$
    – Murta
    Sep 26, 2014 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, 2014 at 22:16
  • $\begingroup$ Similar but more abusive: Re[l1, l2, l3] /. Re@x__ :> x $\endgroup$
    – Mr.Wizard
    Sep 26, 2014 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, 2014 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$
1
  • $\begingroup$ +1 But can't help frowning while shaking my head :) $\endgroup$ Sep 26, 2014 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
  • 1
    $\begingroup$ Ha! I was tempted too :) $\endgroup$ Sep 25, 2014 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$
1
  • $\begingroup$ The desired output is {a, d, g, {b, c, e, f, h, i}} :D $\endgroup$ Sep 25, 2014 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 and acknowledge you have read our privacy policy.

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