Skip to main content
4 of 5
Fix missing semicolon
Carl Woll
  • 131.7k
  • 6
  • 246
  • 359
f[a_] := Module[{b, startpos, endpos},
 
 b = Differences[Subtract[1 , UnitStep[-Differences[a]]]];
 (* for "nondescending" use this instead:*)
 (* b = Differences[UnitStep[Differences[a]]];*)
 startpos = Flatten[Position[b, 1]] + 1;
 endpos = Flatten[Position[b, -1]] + 1;
 If[startpos[[-1]] > endpos[[-1]], endpos = Join[endpos, {Length[a]}]];
 If[startpos[[1]] > endpos[[1]], startpos = Join[{1}, startpos]];
 Take[a, #] & /@ Transpose[{startpos, endpos}]
 ]

Now,

f[{1, -1, 2, 3, 4, 0, -2, 5, 0}]

{{-1, 2, 3, 4}, {-2, 5}}

#Edit

Here is the same function accelerated by Nearest (instead of Position) and a compiled routine to produce the sublists (instead of Take):

f2[a_] := Module[{b, startpos, endpos},
  b = Differences[Subtract[1, UnitStep[-Differences[a]]]];
  (*b=Differences[UnitStep[Differences[a]]];*)
  {startpos, endpos} = Nearest[b -> Automatic, {1, -1}] + 1;
  If[startpos[[-1]] > endpos[[-1]], endpos = Join[endpos, {Length[a]}]];
  If[startpos[[1]] > endpos[[1]], startpos = Join[{1}, startpos]];
  Compile[{{a, _Integer, 1}, {startpos, _Integer}, {endpos, _Integer}},
    a[[startpos ;; endpos]],
    RuntimeAttributes -> {Listable},
    Parallelization -> True
    ][a, startpos, endpos]
  ]

Test:

a = RandomInteger[{-100, 100}, {1000000}];
r1 = f[a]; // RepeatedTiming // First
r2 = f2[a]; // RepeatedTiming // First
r1 == r2

1.0

0.23

True

Henrik Schumacher
  • 109.5k
  • 7
  • 186
  • 323