I have a list as follows
lis= {a, {{{b}, {c,d,e}}, {{f}, {g,h,i}}}}
which I would like to flatten to
flattenLis={a,{b,c,d,e},{f,g,h,i}}
Does anyone have a hint. All my flatten attempts did not work. Thanks
I have a list as follows
lis= {a, {{{b}, {c,d,e}}, {{f}, {g,h,i}}}}
which I would like to flatten to
flattenLis={a,{b,c,d,e},{f,g,h,i}}
Does anyone have a hint. All my flatten attempts did not work. Thanks
Here is an approach where I apply the flattening "from the bottom up" (negative level specification). This works by operating on {lis} instead of lis, in order to have sufficiently many levels even when there's no list wrapping an element, such as a:
Flatten[Map[Flatten, {lis}, {-3}], 2]
(* ==> {a, {b, c, d, e}, {f, g, h, i}} *)
My approach also works for this example:
lis2 = {a, {{{b}, {c, d, e}}, {{f}, {g, h, i}}}, b};
Flatten[Map[Flatten, {lis2}, {-3}], 2]
(* ==> {a, {b, c, d, e}, {f, g, h, i}, b} *)
Not sure how general it will be:
{#, ## & @@ Flatten /@ #2} & @@ lis
{a, {b, c, d, e}, {f, g, h, i}}
{#1, Flatten /@ #2} & @@ lis(*==>{a, {{b, c, d, e}, {f, g, h, i}}}*) 2) {#, ## & @@ #2} & @@ % (*==> {a, {b, c, d, e}, {f, g, h, i}}*)
– xyz
Mar 24 '15 at 05:00
One approach:
MapAt[Flatten, lis, {2, All}] ~FlattenAt~ 2
{a, {b, c, d, e}, {f, g, h, i}}
Hopefully some combination of MapAt, Flatten, and FlattenAt will work for any structure you have.
lis = {a, {{{b}, {c, d, e}}, {{f}, {g, h, i}}}, b}. I upvoted anyway, since the question doesn't specify what generalizations are desirable.
– Jens
Mar 23 '15 at 22:49
MapAt::psl: "Position specification {2,All} in MapAt[Flatten,{a,{{{b},{c,d,e}},{{f},{g,h,i}}}},{2,All}] is not an integer or a list of integers. "
– xyz
Mar 24 '15 at 01:26
All and Span within MapAt was (silently) introduced in version 9; see: (31173). There are alternatives in that Q&A that will work in earlier versions.
– Mr.Wizard
Mar 24 '15 at 03:39
lis I get {a, {b, c, d, e}, {f, g, h, i}, b} -- what else do you want?
– Mr.Wizard
Mar 24 '15 at 03:40
lis2 with your method. It errored out, but now I see it works in version 10. In version 8, your answer doesn't even work with the original lis... It's because MapAt in version 8 doesn't seem to accept position specification All. That change isn't mentioned in the version-10 documentation.
– Jens
Mar 24 '15 at 04:12
Also:
lis = {a, {{{b}, {c, d, e}}, {{f}, {g, h, i}}}};
Fold[Apply[## &, #, {#2}] &, lis, {1, 2}]
(* {a, {b, c, d, e}, {f, g, h, i}} *)
And ... ♯ = {## & @@ #, ## & @@@ #2} & @@ ({##}) &'s close relative:
♭ = ## & @@@ (## & @@@ {## & @@@ # & /@ #} & /@ #) &;
Examples:
♭ @ lis
(* {a, {b, c, d, e}, {f, g, h, i}} *)
lis2 = {a, {{{b}, {c, d, e}}, {{f}, {g, h, i}, {x}}}, b};
♭ @ lis2
{a, {b, c, d, e}, {f, g, h, i, x}, b}
lis = {a, {{{b}, {c, d, e}}, {{f}, {g, h, i}}}, b}.
– Jens
Mar 23 '15 at 22:40
lis = {a, {{{b}, {c, d, e}}, {{f}, {g, h, i}, {x}}}, b}; where I added an {x} together with the {f}. Your first approach works, the second still doesn't.
– Jens
Mar 23 '15 at 23:22
\[Sharp] (\[Flat]s cousin) but i cannot find it now.
– kglr
Mar 24 '15 at 18:39
Another approach is rule replacement, which can be restricted to a specific level.
In[16]:=Replace[lis, l_List :> Sequence @@ Flatten[l], {1}] === flattenList
Out[16]=True
I didn't see an easy way to make this one work without Sequence.
I'm not sure I really understand how the example is to be generalised, but this removes all List heads at level 2 and 4:
ReplacePart[lis, Position[lis, List, {#}] & /@ Join[2, 4] -> Sequence]
(* {a, {b, c, d, e}, {f, g, h, i}} *)
{#1, Sequence @@ #2} & @@ Map[Flatten, lis, {-3}]also works:) – xyz Mar 24 '15 at 01:39b = Sqrt[2];. My method does not fail in that circumstance, nor does it fail onlis2despite your assertion. – Mr.Wizard Mar 24 '15 at 03:46Blockif the entries are at least named by symbols that can be blocked. – Jens Mar 24 '15 at 04:19Slotbased approach wouldn't work with mylis2. Anyway, at this point the OP certainly has a lot of methods to choose from... – Jens Mar 24 '15 at 04:31