簡體   English   中英

如何“聯合”重疊范圍到非重疊范圍?

[英]How to "union" overlapping range to non-overlapping range?

問題:任何人都可以提出更好或更 Pythonic 的方法,將重疊范圍對減少到非重疊范圍對嗎?

背景:我有一個表示開始和結束對的元組列表。 我試圖基本上完成所有開始結束對的聯合。 輸入開始結束對具有重疊值,輸出應表示沒有任何重疊的輸入開始結束對。

下面的代碼很接近但錯誤,因為它輸出了一個不在輸入中的額外范圍(我也意識到它不是很好,為什么它是錯誤的)。 誰能提出更好的方法,或者我忽略的一些內置功能?

為基本問題道歉。 謝謝您的幫助!

##create example data
pairA =[(0,5),(10,12)]
pairB =[(1,2),(11,15)]
pairC =[(1,4),(10,12),(15,17)]

#combine the lists to one list
#ultimately may have n number of lists and felt it would be easier to
merged = pairA + pairB +pairC
# produce union of list * unpacks the arguments of a list
listUnion= sorted(set().union(*merged))

#this is the piece of code I am looking at improving
#it creates new start end pairs based on the union
lastElement =listUnion[-1]
outList=[]

for item in listUnion:
    #create start end pair from value i and i+1
    if item != lastElement:
        outList.append((item,listUnion[listUnion.index(item)+1]))
    else:
        #last element of the list, becomes the last element of list pair
        #it can be ignored
        pass
print outList 
"""output: [(0, 1), (1, 2), (2,4), (4, 5), (5, 10), (10, 11), (11, 12), (12, 15), (15, 
17)]
correct output: would not have (5,10) as there is no overlap here in the input """

編輯:添加了此問題的視覺表示在此處輸入圖片說明

這是一個解決方案。 它可能不是很 Pythonic,因為我對 Python 的經驗非常有限,但它有效。

pairs_a = [(0, 5), (10, 12)]
pairs_b = [(1, 2), (11, 15)]
pairs_c = [(1, 4), (10, 12), (15, 17)]

merged = pairs_a + pairs_b + pairs_c
merged.sort()

set_list = []
cur_set = set()
cur_max = merged[0][1]
for pair in merged:
    p0, p1 = pair
    if cur_max < p0:
        set_list.append(cur_set)
        cur_set = set()
    cur_set.add(p0)
    cur_set.add(p1)
    if cur_max < p1:
        cur_max = p1
set_list.append(cur_set)

out_list = []
for my_set in set_list:
    my_list = sorted(my_set)
    p0 = my_list[0]
    for p1 in my_list[1:]:
        out_list.append((p0, p1))
        p0 = p1

# more pythonic but less readable in spite of indentation efforts:
# out_list = [pair
#             for zipped in [zip(list[:-1], list[1:])
#                            for list in [sorted(set)
#                                         for set in set_list]]
#                 for pair in zipped]

# alternate ending:
# out_list = [sorted(set) for set in set_list]

print(out_list)

這個想法是首先按第一項對所有范圍對進行排序。 這就是merged.sort()所做的(它使用連續的元組成員來消除歧義,但這在這里並不重要)。 然后我們遍歷已排序的范圍對,只要我們在一堆重疊范圍內,我們就將所有開始和結束都添加到當前集合中。 為了知道束何時結束,我們保留所有范圍結束的最大值。 一旦超出此最大值的范圍開始到達,我們通過將其附加到列表來存儲當前集合,並開始一個新集合。 最后一組必須在循環后添加到列表中。 現在我們有一個集合列表,我們可以輕松地將其轉換為列表列表或對列表。

不確定您的環境限制,但如果您沒有,您可能需要考慮這個: https : //pypi.org/project/intervaltree/特別是,

result_tree = tree.union(iterable)

你能澄清一下問題嗎,請。 我看到[(0,5), (1,2)]產生[(0, 1), (1, 2), (2, 5)] [(0,5), (1,5)]產生什么, [(0, 1), (1, 5), (5, 5)] ,或者只是[(0,1)] ,或者別的什么?

暫無
暫無

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

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