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.