找到最长1的序列的起始位置

时间:2016-07-02 15:18:20

标签: python numpy scipy

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

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

我按照answer来查找最长序列的长度。但是,我无法确定这个位置。

6 个答案:

答案 0 :(得分:3)

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

答案 1 :(得分:2)

这似乎有效,使用groupby中的itertools,这只会通过列表一次:

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

答案 2 :(得分:2)

使用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()取出长度的关键功能

打印&#39; 2&#39;如预期的那样。

答案 3 :(得分:1)

您可以使用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

答案 4 :(得分:1)

在单个循环中执行的另一种方法,但不使用itertool的{​​{1}}。

groupby

这也可以使用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

在Python 3中,您无法在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] 参数定义中解包元组,因此最好先使用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)。

答案 5 :(得分:0)

使用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 docstring。