Pythonic方式为最长的连续子序列

时间:2017-10-29 19:58:56

标签: python

我在一个名为“black”的列表中有一个排序的整数列表,我正在寻找一个优雅的方法来获取最长的连续子序列的开始“s”和结束“e”(原始问题有黑色像素)一个wxh位图,我寻找给定列x)中的最长行。我的解决方案有效,但看起来很难看:

# blacks is a list of integers generated from a bitmap this way:
# blacks= [y for y in range(h) if bits[y*w+x]==1]

longest=(0,0)
s=blacks[0]
e=s-1
for i in blacks:
    if e+1 == i:   # Contiguous?
        e=i
    else:
        if e-s > longest[1]-longest[0]:
            longest = (s,e)
        s=e=i
if e-s > longest[1]-longest[0]:
    longest = (s,e)
print longest 

我觉得这可以用聪明的一个或两个班轮来完成

1 个答案:

答案 0 :(得分:1)

您可以使用itertools.groupbyitertools.chain执行以下操作:

from itertools import groupby, chain
l = [1, 2, 5, 6, 7, 8, 10, 11, 12]
f = lambda x: x[1] - x[0] == 1  # key function to identify proper neighbours

以下几乎仍然可读;-)并为您提供一个体面的中间步骤,以更合理的方式进行可能是一个有效的选择:

max((list(g) for k, g in groupby(zip(l, l[1:]), key=f) if k), key=len)
# [(5, 6), (6, 7), (7, 8)]

为了在一行中提取actaul所需的序列[5, 6, 7, 8],你必须使用更多的功夫:

sorted(set(chain(*max((list(g) for k, g in groupby(zip(l, l[1:]), key=f) if k), key=len))))
# [5, 6, 7, 8]

我会留给你来解决这个怪物的内部问题:-)但请记住:单行程在短期内通常是令人满意的,但长期的,更好的选择可读性和代码,你你的同事会明白的。可读性是你提到的Pythonicity的重要组成部分。

另请注意,由于排序,这是O(log_N)。您可以通过应用O(N)重复删除技术之一来实现相同的目标。对OrderedDict的输出chain并保持O(N),但这一行会变得更长。

更新

O(N)方法中的一种是DanD。的建议,可以使用理解技巧在一行中使用,以避免将中间结果分配给变量:

list(range(*[(x[0][0], x[-1][1]+1) for x in [max((list(g) for k, g in groupby(zip(l, l[1:]), key=f) if k), key=len)]][0]))
# [5, 6, 7, 8]

但更漂亮,不是:D