簡體   English   中英

最長連續子序列的Python方法

[英]Pythonic way for longest contiguous subsequence

我在名為“ 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.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)]

為了在一行中提取實際的所需序列[5, 6, 7, 8] 5、6、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]

我會留給您解決這種怪異的內部問題:-),但要記住:單線通常在短期內令人滿意,但從長遠來看,更好地選擇了您和您的合作伙伴的可讀性和代碼工人會明白的。 可讀性是您所暗示的Pythonic的重要組成部分。

還請注意,由於排序,這是O(log_N) 您可以通過將O(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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM