簡體   English   中英

從子區域列表中困惑區域

[英]Puzzling a covered region from list of subregions

我有一長串的值x和y,並按x值的值排序。 我想輸出一個最長連續范圍的x和y值的列表。 說起來有點困難,但是希望通過以下示例可以使它變得清楚:

0, 148
0, 145
0, 186
0, 5768
600, 2374
2376, 2415
3000, 4315
6000, 6616
6000, 6799
6000, 7262

由於任何條目均未覆蓋5768和6000之間的區域,因此以上內容應輸出:

0, 5768
6000, 7262

在我看來,這似乎應該是一個簡單的問題,但是我一直在解決它一段時間。 我已經在下面發布了我的代碼。 我目前的工作問題是,在對x值進行排序的同時,第k行的x值可能超過第k-1行的y值,但沒有標記新的連續字符串的開始。

lines = [line.strip('\n') for line in open('test')]
myarray=[]
for line in lines:
    myarray.append(line.split(', '))

def findCoveredRegions(regionArray):
    resultsContigs = []
    j = regionArray[0][1]
    i = regionArray[0][0]
    for line in regionArray:
        last_i = i
        i = line[0]
        if i <= j:
            if line[1] > j:
                j = line[1]
        else:
            resultsContigs.append([last_i,j])
    resultsContigs.append([i,regionArray[len(regionArray)-1][1]])

    return resultsContigs

print findCoveredRegions(myarray)

這是一個numpy的解決方案

myarray = np.asanyarray(myarray)
order = np.argsort(myarray.ravel())
coverage = np.add.accumulate(1 - 2*(order%2))
gaps = np.where(coverage==0)[0]
left = order[np.r_[0, gaps[:-1] + 1]]
right = order[gaps]
result = myarray.ravel()[np.c_[left, right]]

它匯集並排序所有邊界。 然后從左到右計數遇到的左(+1)和右(-1)個邊界。 這個數字永遠不會為負,只有在存在差距的地方才降至零。 從間隙的位置重建覆蓋的間隔。

這不會特別快,但是我認為它相當Python且可讀。 它不需要或使用間隔的排序列表。

intervals = [(0, 148),
 (0, 145),
 (0, 186),
 (0, 5768),
 (600, 2374),
 (2376, 2415),
 (3000, 4315),
 (6000, 6616),
 (6000, 6799),
 (6000, 7262)]


def intersect(interval_a, interval_b):
    """Return whether two intervals intersect"""
    (a_bottom, a_top), (b_bottom, b_top) = interval_a, interval_b
    return a_bottom <= b_top and b_bottom <= a_top


def union_one_one(interval_a, interval_b):
    """Return the union of two intervals"""
    (a_bottom, a_top), (b_bottom, b_top) = interval_a, interval_b
    return min(a_bottom, b_bottom), max(a_top, b_top)


def union_many_one(old_intervals, new_interval):
    """Return the union of a new interval with several old intervals."""
    result = []
    for old_interval in old_intervals:
        # If an old interval intersects with the new interval, merge the old interval into the new one.
        if intersect(old_interval, new_interval):
            new_interval = union_one_one(old_interval, new_interval)    
        # Otherwise, leave the old interval alone.
        else:
            result.append(old_interval)
    result.append(new_interval)
    return result


def union_all(intervals):
    """Return the union of a collection of intervals"""
    result = []
    for interval in intervals:
        result = union_many_one(result, interval)
    return result            


print(union_all(intervals))

暫無
暫無

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

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