Return last number in sub-sequences in a list of integers
You can use Split
:
Last /@ Split[z, #2 == # + 1&]
{113, 121, 476, 529, 538, 544}
First /@ Split[z, #2 == # + 1&]
{113, 117, 475, 529, 538, 542}
Use a "background" element of the desired difference in SparseArray
on the differences, and "AdjacencyLists"
will pick out what you desire:
Last in sequence:
positions = Append[SparseArray[Differences@z, Automatic, 1], 0]["AdjacencyLists"]
(* {1, 6, 8, 9, 10, 13} *)
z ~Part~ positions // Normal
(* {113, 121, 476, 529, 538, 544} *)
More efficient version:
Append[
z ~Part~
SparseArray[Rest@z - Most@z, Automatic, 1]["AdjacencyLists"],
Last@z]
First in sequence:
Prepend[
Reverse@z ~Part~
Reverse[SparseArray[Rest@z - Most@z, Automatic, 1]]["AdjacencyLists"],
First@z]
(* {113, 117, 475, 529, 538, 542} *)
My answer is similar to Mr.Wizard's answer to Find subsequences of consecutive integers inside a list, which asks for the essentially same thing as the OP but with the output in a different form.
Pick
in combination with vectorized arithmetic is as fast as SparseArray
:
myLastInSequenceV3[z_] := Join[Pick[Most[z], Unitize[Rest[z]-Most[z]-1], 1], {Last[z]}]
Alternative version. Shorter, but slower:
myLastInSequence[z_] := Pick[z, Join[Differences[z], {0}], Except[1, _Integer]]
Test:
LastinSequence[z] == myLastInSequence[z] == myLastInSequenceV3[z]
True
Timing for SparseArray
-based solution:
data = NestList[(# + RandomInteger[9]) &, 1, 100000];
lastInSequenceSparseUpd[z_] := Append[z ~Part~SparseArray[Rest@z - Most@z, Automatic, 1]["AdjacencyLists"],Last@z]
First@RepeatedTiming[lastInSequenceSparseUpd[data];]
0.0018
This method:
First@RepeatedTiming[myLastInSequenceV3[data];]
0.0019