3 ms·
Here's my version, which has one loop for increasing sequences, and another loop for decreasing sequences. I think that makes it easier to understand what's go
by comex 5y ago
Here's my version, which has one loop for increasing sequences, and another loop for decreasing sequences. I think that makes it easier to understand what's going on. It properly handles runs of equal elements, and it handles neither-greater-nor-lesser values like NaN in a relatively principled fashion: putting them in a run by themselves. Perhaps this code is over-commented.
from more_itertools import peekable
def mono_runs(seq):
it = peekable(iter(seq))
while it: # While any elements left...
# Consume the first element.
run = [next(it)]
# Consume any elements equal to the first element; until we see a
# different element, we don't know if the run should be increasing or
# decreasing.
while it and it.peek() == run[-1]:
run.append(next(it))
# Consume the rest of the run.
if it and it.peek() > run[-1]:
# Next is a higher element; this is an increasing sequence.
while it and it.peek() >= run[-1]:
run.append(next(it))
elif it and it.peek() < run[-1]:
# Next is a lower element; this is a decreasing sequence.
while it and it.peek() <= run[-1]:
run.append(next(it))
run.reverse()
# Else, either we're out of elements, or the next element is neither
# higher nor lower (e.g. NaN). Either way, the run ends here.
yield run