Python 函数查找列表中最长运行的开始和结束的索引

Python 函数查找列表中最长运行的开始和结束的索引,python,Python,我试图编写代码,在布尔值列表中查找最长的运行,并返回该运行的第一个和最后一个值的索引。例如,如果L是[假,假,真,假,假,假,假,真,真,假,假]。然后函数将返回(3,6),因为False的最长运行时间是从3到6。这是我到目前为止所做的,但它不能正常工作 def longestFalse(L): endindex = 0 maxcount=0 counter=0 for i in range(len(L)): if L[i] == False: counter += 1

我试图编写代码,在布尔值列表中查找最长的运行,并返回该运行的第一个和最后一个值的索引。例如,如果L是[假,假,真,假,假,假,假,真,真,假,假]。然后函数将返回(3,6),因为False的最长运行时间是从3到6。这是我到目前为止所做的,但它不能正常工作

def longestFalse(L):
endindex = 0
maxcount=0
counter=0
for i in range(len(L)):
    if L[i] == False:
        counter += 1
    elif L[i] == True:
        if counter>maxcount:
            maxcount = counter
            endindex = i
            counter = 0
    elif i == len(L) - 1 :
        if L[i-1] == L[i]:
            counter += 1
            maxcount = count
            endindex = i
return endindex-maxcount,endindex-1
使用:

输出

(3, 6)

更快速的迭代版本,具有
itertools.groupby
功能:

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)

时间性能比较(与前面的答案):


您可以跟踪开始索引和到目前为止最长运行的长度,以及当前运行的开始索引,如果当前索引减去当前运行的开始索引大于到目前为止最长运行的长度,将当前启动指数和所述长度作为新启动指数和最长运行长度:

def longest_false(L):
    start = max_start = None
    max_size = -1
    for i, v in enumerate(L):
        if v:
            start = None
        else:
            if start is None:
                start = i
            if i - start > max_size:
                max_start = start
                max_size = i - start
    if max_start is None:
        return None, None # in case there is no False at all in the given list
    return max_start, max_start + max_size

这在
[True,False]
的情况下失败。哦,真的。那就修好了。
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)
def longest_false(L):
    start = max_start = None
    max_size = -1
    for i, v in enumerate(L):
        if v:
            start = None
        else:
            if start is None:
                start = i
            if i - start > max_size:
                max_start = start
                max_size = i - start
    if max_start is None:
        return None, None # in case there is no False at all in the given list
    return max_start, max_start + max_size