5
$\begingroup$

The FirstPosition[] function can be use to locate the first position of an occurrence in a list. For example FirstPosition[list,_?NumericQ] will find the position of the first occurrence of a number in a list. Is there a function to find the last position of a occurrence? If not perhaps someone has a clever way to do it.

$\endgroup$
  • 1
    $\begingroup$ FirstPosition[Reverse@list,_?NumericQ]?:) $\endgroup$ – kglr Mar 16 '15 at 16:49
  • 2
    $\begingroup$ Don't forget: one then needs to do the proper counting: Length[list]-FirstPostion[Reverse@list,_?NumericQ]. $\endgroup$ – David G. Stork Mar 16 '15 at 16:50
  • $\begingroup$ @David, right... whoops;) $\endgroup$ – kglr Mar 16 '15 at 16:56
  • $\begingroup$ @DavidG.Stork Actually some testing shows you need (Length[list]+1)-FirstPosition[list,_?NumericQ] $\endgroup$ – Wintermute Mar 16 '15 at 17:25
  • 2
    $\begingroup$ ... it gets more complicated if list is not a flat list. For nested lists such as expr={{a,b,2},{c,3,{x,5}},{u,r}}, Position[expr,_?NumericQ,Infinity][[-1]] is much simpler than anything using FirstPosition. $\endgroup$ – kglr Mar 16 '15 at 17:42
5
$\begingroup$

The clean but inefficient way is to simply find all positions and take the last one:

x = {16, {10, {78, 1}, 32, 15}, 30, 30}

Position[x, _?OddQ][[-1]]
{2, 4}

It proves faster to reverse everything and use FirstPosition:

lastPosition[x_, pat_] :=
  Module[{rev, pos},
    rev = Reverse[HoldComplete[x], 1 + Range @ Depth @ x];
    pos = Rest @ FirstPosition[rev, pat];
    1 - pos + Length /@ Unevaluated @@@ FoldList[Part[#, {1}, #2] &, rev, Most@pos]
  ]

lastPosition[x, _?OddQ]
{2, 4}

Timing on a large expression:

SeedRandom[4]
x =
 Nest[
   RandomChoice[{
     {#, #2} &,
     {#2, #} &,
     Prepend,
     Append
   }][#, RandomInteger[99]] &,
   {1},
   2000
 ];

Needs["GeneralUtilities`"]

Position[x, _?OddQ][[-1]] // AccurateTiming
lastPosition[x, _?OddQ]   // AccurateTiming
0.374521

0.000297869

Both output:

{2, 1, 1, 1, 3, 2, 2, 2, 4}
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.