From: Jezzybear on
I am trying to create a function myflat[list] to mimic the behavior of
Mathematica's Flatten[]
function.Example:
In[1]:= myflat[{{{a}}, {b, c}, {d}}]
Out[1]= {a, b, c, d}
In[2]:= myflat[{{}, 1, {{2}}}]
Out[2]= {1, 2}
However in writing this function I want to use only Mathematica's
pattern matching features, the functions
First[], Rest[], Prepend[], ListQ[]. I am trying to do this using some
subfunctions like creating one called myjoin


From: Leonid Shifrin on
Hi,

How about this:

Clear[myFlatten];
myFlatten[x_List] :=
x //. y_ :> Replace[y, {a___, {b___}, c___} :> {a, b, c}, {0}]

My first attempt by the way was a simpler one:

Clear[myFlattenNaive]
myFlattenNaive[x_List] := x //. {a___, {b___}, c___} :> {a, b, c};

This looks ok, but fails in the following case, for example:

In[1]:= {a,b,{c,{d,{e,f,g[h,{i,j,{k}}]}}}}//myFlattenNaive

Out[1]= {a,b,c,d,e,f,g[h,{i,j,k}]}

The wrong thing is that it flattens lists also inside ofther heads, and this
is not what Flatten does. The more complex version does not do it:

In[2]:= {a,b,{c,{d,{e,f,g[h,{i,j,{k}}]}}}}//myFlatten

Out[2]= {a,b,c,d,e,f,g[h,{i,j,{k}}]}

The added advantage of the myFlatten solution is that it is easy to add to
it a level specification as an optional parameter to make myFlatten flatten
on a specific level, if this is needed.

Needless to say, for deeply nested / complex lists with many sublists on the
same level, myFlattenwill be grossly inefficient.

Regards,
Leonid



On Fri, Dec 4, 2009 at 12:31 PM, Jezzybear <jezzybear19(a)hotmail.co.uk>wrote:

> I am trying to create a function myflat[list] to mimic the behavior of
> Mathematica's Flatten[]
> function.Example:
> In[1]:= myflat[{{{a}}, {b, c}, {d}}]
> Out[1]= {a, b, c, d}
> In[2]:= myflat[{{}, 1, {{2}}}]
> Out[2]= {1, 2}
> However in writing this function I want to use only Mathematica's
> pattern matching features, the functions
> First[], Rest[], Prepend[], ListQ[]. I am trying to do this using some
> subfunctions like creating one called myjoin
>
>
>

From: Adriano Pascoletti on
A solution using ReplaceRepeated (//.):

In[1]:= rule = {pre___, L_List, post___} :> {pre, Sequence @@ L, post};
In[2]:= {{{a}}, {b, c}, {d}} //. rule
Out[2]= {a, b, c, d}
In[3]:= {{}, 1, {{2}}} //. rule
Out[3]= {1, 2}


Adriano Pascoletti

2009/12/4 Jezzybear <jezzybear19(a)hotmail.co.uk>

> I am trying to create a function myflat[list] to mimic the behavior of
> Mathematica's Flatten[]
> function.Example:
> In[1]:= myflat[{{{a}}, {b, c}, {d}}]
> Out[1]= {a, b, c, d}
> In[2]:= myflat[{{}, 1, {{2}}}]
> Out[2]= {1, 2}
> However in writing this function I want to use only Mathematica's
> pattern matching features, the functions
> First[], Rest[], Prepend[], ListQ[]. I am trying to do this using some
> subfunctions like creating one called myjoin
>
>
>


From: Leonid Shifrin on
Leslie,

how about this then:

Clear[myFlatten];
With[{join =
Which[#2 === {}, #1,
! ListQ[#2], Append[#1, #2],
{First@#2} === #2, #0[#1, First@#2],
True, Append[#0[#1, Most@#2], Last@#2]] &},
myFlatten[{}] = {};
myFlatten[x_?ListQ] /; {First@x} === x && ! ListQ[First@x] := x;
myFlatten[x_?ListQ] :=
join[myFlatten(a)First@x, myFlatten(a)Rest@x];
myFlatten[x_] := {x}];


It's kind of tricky, but uses only the functions you asked about - I even
avoided using Length. For example:

In[1]:= myFlatten[{a,b,{c,{d,{e,f,g[h,{i,j,{k}}]}}}}]

Out[1]= {a,b,c,d,e,f,g[h,{i,j,{k}}]}

In[2]:= myFlatten[{{1,2,3}}]

Out[2]= {1,2,3}

Now, some implementation details: the function uses double recursion. One
recursion is realized by myFlatten itself, and another is realized by
<join>, which is just an alias for a recursive pure function that joins
together two lists. Perhaps the hardest to digest part is how the recursive
pure function <join> works. If I remember correctly, recursive pure
functions are documented but very briefly. You may get a handle on them by
implementing some simple functions like factorial, Fibonacci or the like in
this style. Alternatively, one could implement it without this construct,
but then a new auxilliary head (say <join>) must be introduced. Here is how
the code for <join> can look like then:

Clear[join];
join[x_?ListQ, y_?(! ListQ[#] &)] := Append[x, y];
join[x_, {}] := x;
join[x_?ListQ, y_ /; {First@y} === y] := join[x, First@y];
join[x_?ListQ, y_] := Append[join[x, Most@y], Last@y];


Regards,
Leonid





On Fri, Dec 4, 2009 at 5:37 PM, Leslie Kanthan <jezzybear19(a)hotmail.co.uk>wrote:

> myFlattenSubfunction[tlist_] /;
> Depth[tlist] <=
> 1 := tlist
> myFlattenSubfunction[tlist_List] :=
> Sequence @@@
> myFlattenSubfunction /@
> tlist
> myFlatten[tlist_] := myFlattenSubfunction[tlist]
> myFlatten[k]
>
> I did the above, but my problem is it does not use First[], Rest[],
> Prepend[], ListQ[] ... I can see what you mean by your code, I never thought
> of using the replace, but its a function that I am trying to avoid using.
> However whichever way by using only First[], Rest[], Prepend[], ListQ[], the
> code will be enefficent i just want to see how far I can get at disementing
> the nested list.
>
> I would be most pleased if you can show me how I may use First[], Rest[],
> Prepend[], ListQ[] along with the said pattern function. Thanks
>
> ------------------------------
> Date: Fri, 4 Dec 2009 15:53:50 +0300
> Subject: Re: Flatten alternative
> From: lshifr(a)gmail.com
> To: jezzybear19(a)hotmail.co.uk; mathgroup(a)smc.vnet.net
>
>
> Hi,
>
> How about this:
>
> Clear[myFlatten];
> myFlatten[x_List] :=
> x //. y_ :> Replace[y, {a___, {b___}, c___} :> {a, b, c}, {0}]
>
> My first attempt by the way was a simpler one:
>
> Clear[myFlattenNaive]
> myFlattenNaive[x_List] := x //. {a___, {b___}, c___} :> {a, b, c};
>
> This looks ok, but fails in the following case, for example:
>
> In[1]:= {a,b,{c,{d,{e,f,g[h,{i,j,{k}}]}}}}//myFlattenNaive
>
> Out[1]= {a,b,c,d,e,f,g[h,{i,j,k}]}
>
> The wrong thing is that it flattens lists also inside ofther heads, and
> this is not what Flatten does. The more complex version does not do it:
>
> In[2]:= {a,b,{c,{d,{e,f,g[h,{i,j,{k}}]}}}}//myFlatten
>
> Out[2]= {a,b,c,d,e,f,g[h,{i,j,{k}}]}
>
> The added advantage of the myFlatten solution is that it is easy to add to
> it a level specification as an optional parameter to make myFlatten flatten
> on a specific level, if this is needed.
>
> Needless to say, for deeply nested / complex lists with many sublists on
> the same level, myFlattenwill be grossly inefficient.
>
> Regards,
> Leonid
>
>
>
> On Fri, Dec 4, 2009 at 12:31 PM, Jezzybear <jezzybear19(a)hotmail.co.uk>wrote:
>
> I am trying to create a function myflat[list] to mimic the behavior of
> Mathematica's Flatten[]
> function.Example:
> In[1]:= myflat[{{{a}}, {b, c}, {d}}]
> Out[1]= {a, b, c, d}
> In[2]:= myflat[{{}, 1, {{2}}}]
> Out[2]= {1, 2}
> However in writing this function I want to use only Mathematica's
> pattern matching features, the functions
> First[], Rest[], Prepend[], ListQ[]. I am trying to do this using some
> subfunctions like creating one called myjoin
>
>
>
>
> ------------------------------
> Have more than one Hotmail account? Link them together to easily access
> both. <http://clk.atdmt.com/UKM/go/186394591/direct/01/>
>


From: Norbert Marxer on
On Dec 4, 10:32 am, Jezzybear <jezzybea...(a)hotmail.co.uk> wrote:
> I am trying to create a function myflat[list] to mimic the behavior of
> Mathematica's Flatten[]
> function.Example:
> In[1]:= myflat[{{{a}}, {b, c}, {d}}]
> Out[1]= {a, b, c, d}
> In[2]:= myflat[{{}, 1, {{2}}}]
> Out[2]= {1, 2}
> However in writing this function I want to use only Mathematica's
> pattern matching features, the functions
> First[], Rest[], Prepend[], ListQ[]. I am trying to do this using some
> subfunctions like creating one called myjoin

Hello

You mean pattern matching like:

myflat[x_] := {x //. List -> Sequence}

Best Regards
Norbert Marxer