我在一个名为“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
我觉得这可以用一个聪明的单线或两线来完成
您可以使用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)]
为了[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
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句