Function to find the index of the beginning and end of the longest run in a list

前端 未结 3 652
抹茶落季
抹茶落季 2021-01-29 10:16

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

3条回答
  •  春和景丽
    2021-01-29 10:48

    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)
    

提交回复
热议问题