【问题标题】:find the start position of the longest sequence of 1's找到最长的 1 序列的起始位置
【发布时间】:2016-07-02 15:18:20
【问题描述】:

我想在我的数组中找到最长的 1 序列的起始位置:

a1=[0,0,1,1,1,1,0,0,1,1]
#2

我正在关注这个answer 来查找最长序列的长度。但是,我无法确定位置。

【问题讨论】:

    标签: python numpy scipy


    【解决方案1】:

    this solution的启发,这里有一个矢量化的方法来解决它-

    # Get start, stop index pairs for islands/seq. of 1s
    idx_pairs = np.where(np.diff(np.hstack(([False],a1==1,[False]))))[0].reshape(-1,2)
    
    # Get the island lengths, whose argmax would give us the ID of longest island.
    # Start index of that island would be the desired output
    start_longest_seq = idx_pairs[np.diff(idx_pairs,axis=1).argmax(),0]
    

    示例运行 -

    In [89]: a1 # Input array
    Out[89]: array([0, 0, 1, 1, 1, 1, 0, 0, 1, 1])
    
    In [90]: idx_pairs # Start, stop+1 index pairs
    Out[90]: 
    array([[ 2,  6],
           [ 8, 10]])
    
    In [91]: np.diff(idx_pairs,axis=1) # Island lengths
    Out[91]: 
    array([[4],
           [2]])
    
    In [92]: np.diff(idx_pairs,axis=1).argmax() # Longest island ID
    Out[92]: 0
    
    In [93]: idx_pairs[np.diff(idx_pairs,axis=1).argmax(),0] # Longest island start
    Out[93]: 2
    

    【讨论】:

    • 漂亮的解决方案!
    【解决方案2】:

    这似乎有效,使用来自itertoolsgroupby,这只通过列表一次:

    from itertools import groupby
    
    pos, max_len, cum_pos = 0, 0, 0
    
    for k, g in groupby(a1):
        if k == 1:
            pat_size = len(list(g))
            pos, max_len = (pos, max_len) if pat_size < max_len else (cum_pos, pat_size)
            cum_pos += pat_size
        else:
            cum_pos += len(list(g))
    
    pos
    # 2
    max_len
    # 4
    

    【讨论】:

      【解决方案3】:

      使用groupby() 的更紧凑的单行。在原始数据上使用enumerate() 以保持通过分析管道的起始位置,最终以元组列表结束 [(2, 4), (8, 2)] 每个元组包含非起始位置和长度零次运行:

      from itertools import groupby
      
      L = [0,0,1,1,1,1,0,0,1,1]
      
      print max(((lambda y: (y[0][0], len(y)))(list(g)) for k, g in groupby(enumerate(L), lambda x: x[1]) if k), key=lambda z: z[1])[0]
      

      lambda: xgroupby() 的关键函数,因为我们枚举了 L

      lambda: y 将我们需要的结果打包,因为我们只能评估一次g,而不会保存

      lambda: zmax()拉出长度的关键函数

      按预期打印“2”。

      【讨论】:

        【解决方案4】:

        您可以使用 for 循环并检查接下来的几个项目(长度为 m,其中 m 是最大长度)是否与最大长度相同:

        # Using your list and the answer from the post you referred
        from itertools import groupby
        L = [0,0,1,1,1,1,0,0,1,1]
        m = max(sum(1 for i in g) for k, g in groupby(L))
        # Here is the for loop
        for i, s in enumerate(L):
            if len(L) - i + 2 < len(L) - m:
                break
            if s == 1 and 0 not in L[i:i+m]:
                print i
                break
        

        这将给出:

        2
        

        【讨论】:

          【解决方案5】:

          在单个循环中执行的另一种方式,但不诉诸 itertoolgroupby

          max_start = 0
          max_reps = 0
          start = 0
          reps = 0
          for (pos, val) in enumerate(a1):
              start = pos if reps == 0 else start
              reps = reps + 1 if val == 1 else 0
              max_reps = max(reps, max_reps)
              max_start = start if reps == max_reps else max_start
          

          这也可以使用reduce 以单行方式完成:

          max_start = reduce(lambda (max_start, max_reps, start, reps), (pos, val): (start if reps == max(reps, max_reps) else max_start, max(reps, max_reps), pos if reps == 0 else start, reps + 1 if val == 1 else 0), enumerate(a1), (0, 0, 0, 0))[0]
          

          在 Python 3 中,您无法解压缩 lambda 参数定义中的元组,因此最好先使用 def 定义函数:

          def func(acc, x):
              max_start, max_reps, start, reps = acc
              pos, val = x
              return (start if reps == max(reps, max_reps) else max_start,
                      max(reps, max_reps),
                      pos if reps == 0 else start,
                      reps + 1 if val == 1 else 0)
          
          max_start = reduce(func, enumerate(a1), (0, 0, 0, 0))[0]
          

          在这三种情况中的任何一种情况下,max_start 都会给出您的答案(即2)。

          【讨论】:

            【解决方案6】:

            使用第三方库more_itertools

            给定

            import itertools as it
            
            import more_itertools as mit
            
            
            lst = [0, 0, 1, 1, 1, 1, 0, 0, 1, 1]
            

            代码

            longest_contiguous = max([tuple(g) for _, g in it.groupby(lst)], key=len)
            longest_contiguous    
            # (1, 1, 1, 1)
            
            pred = lambda w: w == longest_contiguous
            next(mit.locate(mit.windowed(lst, len(longest_contiguous)), pred=pred))
            # 2
            

            有关这些工具如何工作的详细信息,另请参阅more_itertools.locate 文档字符串。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2020-04-14
              • 1970-01-01
              • 2017-06-22
              • 1970-01-01
              • 2011-06-23
              • 1970-01-01
              相关资源
              最近更新 更多