检查两个时间间隔是否重叠



我有两个不同的间隔集:

Intervals1:
{'ending_time': '2016-02-26 07:10:40.276504', 'starting_time': '2016-02-26 07:10:39.286168'}
{'ending_time': '2016-02-26 07:10:40.722193', 'starting_time': '2016-02-26 07:10:40.301116'}
{'ending_time': '2016-02-26 07:10:41.329731', 'starting_time': '2016-02-26 07:10:40.812676'}
{'ending_time': '2016-02-26 07:10:42.146669', 'starting_time': '2016-02-26 07:10:41.419473'}
{'ending_time': '2016-02-26 07:10:42.413005', 'starting_time': '2016-02-26 07:10:42.203540'}
{'ending_time': '2016-02-26 07:10:42.686456', 'starting_time': '2016-02-26 07:10:42.442964'}
{'ending_time': '2016-02-26 07:10:43.198191', 'starting_time': '2016-02-26 07:10:42.746994'}
{'ending_time': '2016-02-26 07:10:44.502593', 'starting_time': '2016-02-26 07:10:43.288611'}
{'ending_time': '2016-02-26 07:10:46.525823', 'starting_time': '2016-02-26 07:10:44.709627'}
{'ending_time': '2016-02-26 07:10:47.098280', 'starting_time': '2016-02-26 07:10:46.886541'}
--------------------------
Interval2:
{'ending_time': '2016-02-26 07:10:41.482954', 'starting_time': '2016-02-26 07:10:39.590220'}
{'ending_time': '2016-02-26 07:10:42.615738', 'starting_time': '2016-02-26 07:10:41.649375'}
{'ending_time': '2016-02-26 07:10:46.365902', 'starting_time': '2016-02-26 07:10:45.987907'}
{'ending_time': '2016-02-26 07:10:47.698375', 'starting_time': '2016-02-26 07:10:46.510641'}

我用这一行将这些日期时间字符串转换为实时日期时间对象:

datetime.datetime.strptime(dictionary['starting_time'], "%Y-%m-%d %H:%M:%S.%f")

我在这里要做的是通过比较这两个不同的集合来匹配重叠的时间间隔。

例如;间隔 1[0] 和间隔 2[0] 重叠但间隔 1[7] 和间隔 2[0] 不重叠。

那么正确的方法是什么呢?一个简短的解释对我来说就足够了。

datetime对象都支持比较,所以你只需要检查第一个开始时间是否在另一个的开始和结束之间,或者第一个结束时间是否在另一个的开始停止之间,反之亦然。

def overlap(first_inter,second_inter):
    for f,s in ((first_inter,second_inter), (second_inter,first_inter)):
        #will check both ways
        for time in (f["starting_time"], f["ending_time"]):
            if s["starting_time"] < time < s["ending_time"]:
                return True
    else:
        return False

编辑:另请注意,由于日期字符串的格式首先具有最重要的值,因此可以轻松进行比较,而无需将它们放入datetime对象中。

Edit2:这是一个将所有组合及其结果记录到字典中的食谱:

import itertools
combos = {(i1,i2):overlap(int1,int2)
             for (i1,int1),(i2,int2)
                in itertools.product(enumerate(Intervals1),enumerate(Intervals2))}
print(*combos.items(),sep="n")

这样combos[0,1]就会枯萎Intervals[0]Intervals[1]重叠等等。

然后,要获得一组重叠时间,您可以使用:

overlapped = set(com for com,was_overlapped in combos.items() if was_overlapped)

最后编辑:我很抱歉使用非常长的dict理解,以混乱的格式处理数据非常困难,如果原始时间列表有模式,那么仅使用字典理解的 for 循环部分将产生预期的结果:

for (i1,int1),(i2,int2) in itertools.product(enumerate(Intervals1),enumerate(Intervals2)):
    if overlap(int1,int2):
        print(i1,i2)

或者要对overlapped集进行排序,您可以使用内置的sorted

overlapped = sorted(overlapped) #this gives a list

您可以像这样比较范围:

timerange1 = {'ending_time': '2016-02-26 07:10:40.276504', 'starting_time': '2016-02-26 07:10:39.286168'}
timerange2 = {'ending_time': '2016-02-26 07:10:41.482954', 'starting_time': '2016-02-26 07:10:39.590220'}
# use a function to make this 'interval' data structure (instead of me being lazy)
interval1 = [datetime.datetime.strptime(timerange1['starting_time'], "%Y-%m-%d %H:%M:%S.%f")]
             datetime.datetime.strptime(timerange1['ending_time'], "%Y-%m-%d %H:%M:%S.%f")]
interval2 = [datetime.datetime.strptime(timerange2['starting_time'], "%Y-%m-%d %H:%M:%S.%f")]
             datetime.datetime.strptime(timerange2['ending_time'], "%Y-%m-%d %H:%M:%S.%f")]
def overlaps(interval1, interval2):
    results = []
    for timestamp in interval1:
        results.append(interval2[0] < timestamp < interval2[1])
    for timestamp in interval2:
        results.append(interval1[0] < timestamp < interval1[1])
    return True in results

以下内容不需要 4mn,而是只需要对 Intervals1 中的 m 条记录和 Intervals2 中的 n 条记录进行 2mn 次比较。

Intervals1 = [
    {'ending_time': '2016-02-26 07:10:40.276504', 'starting_time': '2016-02-26 07:10:39.286168'},
    {'ending_time': '2016-02-26 07:10:40.722193', 'starting_time': '2016-02-26 07:10:40.301116'},
    {'ending_time': '2016-02-26 07:10:41.329731', 'starting_time': '2016-02-26 07:10:40.812676'},
    {'ending_time': '2016-02-26 07:10:42.146669', 'starting_time': '2016-02-26 07:10:41.419473'},
    {'ending_time': '2016-02-26 07:10:42.413005', 'starting_time': '2016-02-26 07:10:42.203540'},
    {'ending_time': '2016-02-26 07:10:42.686456', 'starting_time': '2016-02-26 07:10:42.442964'},
    {'ending_time': '2016-02-26 07:10:43.198191', 'starting_time': '2016-02-26 07:10:42.746994'},
    {'ending_time': '2016-02-26 07:10:44.502593', 'starting_time': '2016-02-26 07:10:43.288611'},
    {'ending_time': '2016-02-26 07:10:46.525823', 'starting_time': '2016-02-26 07:10:44.709627'},
    {'ending_time': '2016-02-26 07:10:47.098280', 'starting_time': '2016-02-26 07:10:46.886541'}
    ]
Intervals2 = [
    {'ending_time': '2016-02-26 07:10:41.482954', 'starting_time': '2016-02-26 07:10:39.590220'},
    {'ending_time': '2016-02-26 07:10:42.615738', 'starting_time': '2016-02-26 07:10:41.649375'},
    {'ending_time': '2016-02-26 07:10:46.365902', 'starting_time': '2016-02-26 07:10:45.987907'},
    {'ending_time': '2016-02-26 07:10:47.698375', 'starting_time': '2016-02-26 07:10:46.510641'}
    ]
for i1, d1 in enumerate(Intervals1):
  for i2, d2 in enumerate(Intervals2):
    start1 = d1["starting_time"]
    start2 = d2["starting_time"]
    end1 = d1["ending_time"]
    end2 = d2["ending_time"]
    if end1 >= start2 and end2 >= start1:
        print("Intervals1", i1, "overlaps with Intervals2", i2)

又好又短。从同事那里拿来的,不知道作者

)))
def is_overlapped(ranges):
    sorted_ranges = sorted(ranges, key=lambda begin_end: begin_end[0])
    return list(chain(*sorted_ranges)) != sorted(chain(*sorted_ranges))
##

##

不重叠:

打印(is_overlapped([(日期时间(2023, 10, 1), 日期时间(2023, 12, 31)),(日期时间(2020, 11, 1), 日期时间(2020, 12, 2))]))

False

先到二:

print(is_overlapped([ (datetime(2013, 10, 1), datetime(2013, 12, 31)),(日期时间(2000, 11, 1), 日期时间(2020, 12, 2

)) ]))
True

排在第二位:

print(is_overlapped([ (datetime(2013, 10, 1), datetime(2023, 12, 31)),(日期时间(2020, 11, 1), 日期时间(2020, 12, 2

)) ]))
True

第一个变成第二个:

print(is_overlapped([ (datetime(2010, 10, 1), datetime(2013, 12, 31)),(datetime(2013, 11, 1), datetime(2015, 12, 2

)) ]))
True

二变一:

print(is_overlapped([ (datetime(2011, 10, 1), datetime(2013, 12, 31)),(datetime(2010, 11, 1), datetime(2011, 12, 2

)) ]))
True

相关内容

  • 没有找到相关文章