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.