I\'m trying to write code that finds the longest run in a list of Boolean values and return the index of the first and last value of that run. For example, if L is [False, Fals
A more faster iterative version with itertools.groupby
feature:
from itertools import groupby
def get_longest_run(lst):
curr_len, run_span = 0, 0
for k, gr in groupby(lst):
len_ = len(list(gr))
if (run_span and len_ > (run_span[1] + 1) - run_span[0]) or len_ > curr_len:
run_span = (curr_len, curr_len + len_ - 1)
curr_len += len_
return run_span
lst = [False, False, True, False, False, False, False, True, True, False, False]
print(get_longest_run(lst)) # (3, 6)
Time performance comparison (to previous answer):
In [144]: lst = [False, False, True, False, False, False, False, True, True, False, False]
In [145]: def get_longest_run_deniel(lst):
...: start = 0
...: runs = []
...: for key, run in groupby(lst):
...: length = sum(1 for _ in run)
...: runs.append((start, start + length - 1))
...: start += length
...:
...: result = max(runs, key=lambda x: x[1] - x[0])
...: return result
...:
In [146]: def get_longest_run(lst):
...: curr_len, run_span = 0, 0
...: for k, gr in groupby(lst):
...: len_ = len(list(gr))
...: if (run_span and len_ > (run_span[1] + 1) - run_span[0]) or len_ > curr_len:
...: run_span = (curr_len, curr_len + len_ - 1)
...: curr_len += len_
...:
...: return run_span
...:
In [147]: %timeit get_longest_run_deniel(lst)
6.06 µs ± 168 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
In [148]: %timeit get_longest_run(lst)
3.67 µs ± 131 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)