Re: split a list
- To: mathgroup at smc.vnet.net
- Subject: [mg40564] Re: [mg40515] split a list
- From: Andrzej Kozlowski <akoz at mimuw.edu.pl>
- Date: Thu, 10 Apr 2003 03:39:07 -0400 (EDT)
- Sender: owner-wri-mathgroup at wolfram.com
Actually, yours is possibly the most inefficient way to do this (in
Mathematica of course, not in C). To see this let's turn it into a
function:
spl1[r_, m_] := Module[{u = {}, v = {}},
For[i = 1, i ¡Â Length[r], i++, tmp = r[[i]];
If[tmp > m, AppendTo[u, tmp], AppendTo[v, tmp]];]; {u, v}]
Let's compare it with one of the most obious ways to do this in
Mathematica:
spl2[ls_, m_] := {Cases[ls, _?(# > m &)], Cases[ls, _?(# ¡Â m &)]}
Let's take a fairly size test example:
r = Table[Random[], {10^4}];
You can see a pretty big difference in performance:
res1=spl1[r,0.5];//Timing
{11.89 Second,Null}
res2=spl2[r,0.5];//Timing
{0.34 Second,Null}
If one wants to do better than spl2 one should probably try to write a
function that can be compiled (spl2 can't because the Mathematica
compiler can't deal with patterns). I have not been able to see any
obvious way to do this in a singe step but here is a possible two step
approach:
first a compiled auxiliary function:
f=Compile[{{r,_Real,1},{m,_Real,0}},Block[{n=Max[r]+1},Transpose[{If[#>
m,#,n],If[#<=0.5,#,n]}&/@r]]];
then a non-compiled splitting function, which relies on f:
spl3[r_,m_]:=DeleteCases[f[r,m],Max[r]+1,Infinity]
This beats spl2:
res3=spl3[r,0.5];//Timing
{0.13 Second,Null}
We can check that all the answers agree:
In[23]:=
res1==res2==res3
Out[23]=
True
I am sure this can be much improved but this is as much time as I am
prepared to spend on this.
Andrzej Kozlowski
Yokohama, Japan
http://www.mimuw.edu.pl/~akoz/
http://platon.c.u-tokyo.ac.jp/andrzej/
On Wednesday, April 9, 2003, at 02:30 pm, Roberto Brambilla wrote:
> Hi,
>
> I have a list (very long, thousands, and unsorted) of numbers
> r={n1,n2...}
> and for a given a number m I want to split it in the two sublists
> (unsorted, same order) u={elements<m], v={elements>m}.
> Now I use this *old-style* method:
>
> u = v = {};
> For[i = 1, i <= Length[r], i++,
> tmp = r[[i]];
> If[tmp > m , AppendTo[u, tmp], AppendTo[v, tmp]];
> ]
>
> Any suggestion for a more efficient (and elegant) method?
> Also oneliners are well accepted.
>
> Many thanks, Roberto
>
> Roberto Brambilla
> CESI
> Via Rubattino 54
> 20134 Milano
> tel +39.02.2125.5875
> fax +39.02.2125.5492
> rlbrambilla at cesi.it
>
>
>
>