We all know the naive solution: you need to loop over all the items in your list, like in this code
def just_loop_over(ls, k):
found_zero = False
events = []
for i, x in enumerate(ls):
if found_zero:
if x > k:
events.append(i)
found_zero = False
else:
if x == 0:
found_zero = True
return events
So my idea is... loop over the list twice, but let Python builtins do their job - list.index() is far most efficient than anything we could ever write, and if we check for an item greater than K only after a zero, we can reasonably hope to skip a large number of items.
def use_builtins(ls, k):
events = []
zeros = []
z = -1
still_good = True
while still_good:
try:
z = ls.index(0, z + 1)
zeros.append(z)
except:
still_good = False
zeros.append(len(ls))
for z in range(len(zeros) - 1):
for i, x in enumerate(ls[zeros[z] + 1:zeros[z + 1]], start = zeros[z] + 1):
if x > k:
events.append(i)
break
return events
I tried both functions on a random generated list of 10k values ranging from 0 to 999 (so I could expect about ten instances of zero), and the speed gain is about 2.5x, but I expect it should be greater than that on bigger lists.
Of course it depends on how many zeros are in the list and where they are, and where the first item following each zero and greater than K is. So for bigger Ks it will be a bit slower, for smaller Ks a bit faster.
As far as I know, if you want something more efficient, your only option is multiprocessing.