我在一个名为“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
我觉得这可以用聪明的一个或两个班轮来完成
答案 0 :(得分:1)
您可以使用itertools.groupby
和itertools.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