MathGroup Archive 2004

[Date Index] [Thread Index] [Author Index]

Search the Archive

Re: Find last NZ in list

  • To: mathgroup at smc.vnet.net
  • Subject: [mg46191] Re: Find last NZ in list
  • From: Dr Bob <drbob at bigfoot.com>
  • Date: Tue, 10 Feb 2004 00:06:11 -0500 (EST)
  • Reply-to: drbob at bigfoot.com
  • Sender: owner-wri-mathgroup at wolfram.com

A form of "FirstPosition" actually IS built in, and was used in my posted 
solution from a couple of days ago:

nonZero = If[Developer`ZeroQ@#, False, True, True] &;
find = 1 + Length@# - First@First@(Position[Reverse@#, _?nonZero, 1,
     1, Heads -> False] /. {} -> {{1 + Length@#}}) &;

This is twenty or thirty times slower than Andrzej's solution using "=!=", 
but observe:

1 - Cos[x]^2 - Sin[x]^2 =!= 0
True

nonZero[1 - Cos[x]^2 - Sin[x]^2]
False

Therefore, if some of your entries are zero but not OBVIOUSLY zero, all 
the other solutions I've seen will fail. I understood you to be concerned 
about this to some extent.

If "=!=" is good enough, my solution can be changed to this:

find2 = 1 +
     Length@# - First@First@(Position[
         Reverse@#, _?(# =!= 0 &), 1, 1, Heads -> False] /. {} -> {{1 +
                   Length@#}}) &;

Here are timings directly after Quit and defining the functions:

nn=20000;a=Table[0,{nn}];a[[666]]=dante;
Print[Timing[FindLastNonzero[a]]];
Print[Timing[FindLastNonzero1[a]]];
Print[Timing[FindLastNonzero2[a]]];
Print[Timing[find[a]]];
Print[Timing[find2[a]]];

{0.094 Second,666}
{0.093 Second,666}
{0.032 Second,666}
{0.875 Second,666}
{0.031 Second,666}

On a second or later trial, for some reason, the timings are rather 
different:

nn = 20000; a = Table[0, {nn}]; a[[666]] = dante;
Print[Timing[FindLastNonzero[a]]];
Print[Timing[FindLastNonzero1[a]]];
Print[Timing[FindLastNonzero2[a]]];
Print[Timing[find[a]]];
Print[Timing[find2[a]]];
{0.07800000000000007*Second, 666}
{0.0930000000000002*Second,  666}
{0.04699999999999993*Second, 666}
{0.9069999999999998*Second, 666}
{0.03100000000000014*Second, 666}

Bobby

carlos at colorado.edu (Carlos Felippa) wrote in message 
news:<c07ue1$o2e$1 at smc.vnet.net>...
> Many thanks for the submissions.  Here is a comparison of five
> functions and their timings on a mac g4.
>
> FindLastNonzero[a_]:=Module[{n=Length[a]},       For [i=n,i>0,i--, If 
> [a[[i]]==0,Continue[],Return[i],
>     Return[i]]]; Return[0]];  (* CAF *)
> FindLastNonzero1[a_]:=Module[{n=Length[a]},        For [i=n,i>0,i--, If 
> [a[[i]]!=0,Return[i],Continue[],
>     Return[i]]]; Return[0]];  (* CAF *)
> FindLastNonzero2[a_]:=Catch[Do[If[a[[i]]=!=0,Throw[i]],{i,Length[a],1,-1}];0];
>         (* Andrzej Kozlowski *)
> FindLastNonzero3[a_]:=First[Position[a, _?(# == 0 &)]] - 1;    (*
> János Lobb *)
> FindLastNonzero4[lst_]:=
>   Module[{tmp=DeleteCases[lst,0]},
>     If[Length[tmp]!=0,Last[tmp],0]  ];  (* Bo Le *)
> FindLastNonZero5[liste_] :=
>   If[Position[(StringMatchQ[#1, "0"] & ) /@
>       ToString /@ liste, False] != {},
>    Last[Position[(StringMatchQ[#1, "0"] & ) /@
>        ToString /@ liste, False]][[1]], 0];  (* Florian Jaccard *)
>       nn=20000;  a=Table[0,{nn}]; a[[666]]=dante;  
> Print[Timing[FindLastNonzero  [a]]];
> Print[Timing[FindLastNonzero1[a]]];
> Print[Timing[FindLastNonzero2[a]]];     
> Print[Timing[FindLastNonzero3[a]]];    (* fails on this example *)
> Print[Timing[FindLastNonzero4[a]]];    (* returns entry, not index *)
> (* Print[Timing[FindLastNonzero5[a]]];  does not work *) {0.55 
> Second,666}
> {0.4 Second,666}
> {0.133333 Second,666}
> {0.2 Second,{0}}
> {0.0333333 Second,dante}
>
> FindLastNonzero4 is fastest but requires another Position search for
> the entry index .  Of those that work in one shot, FindLastNonzero2 is
> fastest.
>
> The most elegant functional solution would be to say
>   i = FirstPosition[Reverse[a],!=0];
> as a built in function.  But this doesnt exist.





  • Prev by Date: Re: Polylogarithm Integration - Bis
  • Next by Date: MultipleListPlot
  • Previous by thread: Re: Find last NZ in list
  • Next by thread: What is ListConvolve doing here?