![](/img/trans.png)
[英]How to check if two time ranges are overlapping in an efficient manner (Python)
[英]How to 'subtract' overlapping tuple time ranges in two different lists
我有兩個元組列表,每個元組由一個開始和結束時間(從紀元開始的秒數)組成,如下所示:
list1= [(2,4), (7,10), (14,22)]
list2 = [(1,3), (5,8), (9,15), (20,24)]
我需要創建一個新的元組(開始,結束)范圍列表,以刪除list2
的元組與list1
的元組重疊的時間間隔。
給定list1
和list2
,該方法的預期輸出為:
[(3,4), (8,10), (15,20)]
就其價值而言,列表list1
和列表list2
都將包含唯一的時間范圍,即每個單獨的列表內都不會重疊。
這是一個僅在列表的每個元素上迭代一次的解決方案。
使用list1 = [(2, 4), ...]
和list2 = [(1, 3), ...]
,我們得到:
輸出是由我們都在區間內而不是在已刪除部分中的部分組成的。
因此,我們的想法是按順序瀏覽事件,跟蹤我們是否處於間隔中以及是否位於已刪除的部分中。
我們從每個列表創建一個生成器開始,它將生成:
Event(pos=2, toggle='in_interval')
, Event(pos=2, toggle='in_interval')
, Event(pos=4, toggle='in_interval')
等。 Event(pos=1, toggle='in_deleted')
, Event(pos=1, toggle='in_deleted')
, Event(pos=3, toggle='in_deleted')
... 我們不需要關心每個值是間隔的開始還是結束,因為它只是在切換狀態(間隔的內部/外部)。
然后,我們可以使用heapq.merge從這兩個生成器中按順序獲取事件,這將為我們提供以下信息:
Event(pos=1, toggle='in_deleted')
, Event(pos=2, toggle='in_interval')
, Event(pos=3, toggle='in_deleted')
, Event(pos=4, toggle='in_interval')
...
每個事件將切換關聯的狀態。 當我們既處於間隔中又不在刪除的部分中時,我們將為輸出創建一個新的間隔。 其余的不言而喻...
from heapq import merge
from itertools import chain
from collections import namedtuple
def remaining(intervals, deleted):
Event = namedtuple('Event', ['position', 'toggle'])
int_iter = (Event(position=pos, toggle='in_interval') for pos in chain.from_iterable(intervals))
del_iter = (Event(position=pos, toggle='in_deleted') for pos in chain.from_iterable(deleted))
state = {'in_interval': False, 'in_deleted': False}
start = None
out = []
for event in merge(int_iter, del_iter):
state[event.toggle] = not state[event.toggle]
if state['in_interval'] and not state['in_deleted']:
# start a new interval
start = event.position
elif start is not None:
# end an interval. If it's not empty, we append it to the output
if event.position > start:
out.append((start, event.position))
start = None
return out
輸出示例:
list1 = [(2,4), (7,10), (14,22)]
list2 = [(1,3), (5,8), (9,15), (20,24)]
print(remaining(list1, list2))
# [(3, 4), (8, 9), (15, 20)]
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.