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$
6
  • 1
    $\begingroup$ FirstPosition[Reverse@list,_?NumericQ]?:) $\endgroup$
    – kglr
    Commented Mar 16, 2015 at 16:49
  • 2
    $\begingroup$ Don't forget: one then needs to do the proper counting: Length[list]-FirstPostion[Reverse@list,_?NumericQ]. $\endgroup$ Commented Mar 16, 2015 at 16:50
  • $\begingroup$ @David, right... whoops;) $\endgroup$
    – kglr
    Commented Mar 16, 2015 at 16:56
  • $\begingroup$ @DavidG.Stork Actually some testing shows you need (Length[list]+1)-FirstPosition[list,_?NumericQ] $\endgroup$
    – Wintermute
    Commented Mar 16, 2015 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
    Commented Mar 16, 2015 at 17:42

1 Answer 1

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$
0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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