15
$\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

11
$\begingroup$

How about this

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

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

$\endgroup$
10
$\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$ Commented 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$ Commented Sep 26, 2014 at 14:41
9
$\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$ Commented 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$ Commented Sep 26, 2014 at 17:51
  • $\begingroup$ thank you @Michael; updated with something along those lines. $\endgroup$ Commented Sep 26, 2014 at 18:07
  • $\begingroup$ This is evil. I approve. $\endgroup$ Commented Sep 26, 2014 at 21:52
  • 1
    $\begingroup$ (1137) $\endgroup$ Commented Sep 26, 2014 at 22:02
  • 1
    $\begingroup$ Yep, I can imagine in a near future #~♯~# == 42. @Mr.Wizard remember to give attribution. $\endgroup$ Commented 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$
5
$\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$ Commented 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$ Commented Sep 26, 2014 at 22:16
  • $\begingroup$ Similar but more abusive: Re[l1, l2, l3] /. Re@x__ :> x $\endgroup$ Commented 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$ Commented Sep 27, 2014 at 4:50
4
$\begingroup$

This is another way:

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

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

$\endgroup$
3
$\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$ Commented Sep 25, 2014 at 23:03
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$ Commented Sep 26, 2014 at 15:01
3
$\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$ Commented Sep 25, 2014 at 23:02
2
$\begingroup$

Another solution :

Join[#[[1]], {#[[2]]}] &@(Flatten /@ Transpose@{l1, l2, l3})
(* {a, d, g, {b, c, e, f, h, i}} *)
$\endgroup$
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.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.