Find the locally biggest or equal values including corners in an array
First off you can change the while loop to a for loop.

for i in range(1, len(vals)):


This makes the program easier to understand. As then there is no i += 1.



It is also un-pythonic to do:

if len(vals) == 0:


Instead do:

if not vals:




As you want it to work with edge cases, what about generators? And other objects that are iterable, but not index-able.

I would change the if not vals: to a try except.

vals = iter(vals)
try:
    prev = next(vals)
except StopIteration:
    return []


And then you can change the for loop to use enumerate.

for i, curr in enumerate(vals, 1):
    if curr &gt; prev:
        is_candidate = True
        buff = [i]
    elif curr == prev and is_candidate:
        buff.append(i)
    else:
        if is_candidate:
            res += buff
        is_candidate = False
        buff = []
    prev = curr


now it will work with anything that is iterable. And so it will work with generators.



Both yield and list.append are \$O(1)\$. However I like to think that list.append is \$O(n)\$. This is as lists rely on the amortized worst case to be \$O(1)\$.

From the Python time complexity page.


  Internally, a list is represented as an array; the largest costs come from growing beyond the current allocation size (because everything must move)


So using range, assuming you're using Python3, and generators can be better.

def look_for_maximas(vals): 
    def res(vals):
        vals = iter(vals)
        # Exploiting for-loops and generators. It's kinda surprising this works.
        prev = next(vals)

        start = 0
        # Has to be in scope for the last yield.
        i = 1
        for curr in vals:
            if curr &gt; prev:
                start = i
            elif curr &lt; prev:
                if start is not None:
                    yield range(start, i)
                start = None
            prev = curr
            i += 1

        if start is not None:
            yield range(start, i)

    for range_ in res(vals):
        for i in range_:
            yield i


It is not as fast as a NumPy or SciPi solution, but can be a lot faster than using lists.

I tested this by doing assert list(look_for_maximas(...)) == .... And it worked for them all. However I don't have repeat, and removed that test.