Psudo代码:
timelines = [
(range(<from>, <to>), range(<from>, <to>)),
(range(<from>, <to>), range(<from>, <to>)),
(range(<from>, <to>), range(<from>, <to>)),
]
<from>
和<to>
代表日期时间对象
这&#34;图片&#34;在&#34; Intersection&#34;之后显示我需要计算的值:
|----------| |----------|
|------------| |-------|
|---------| |------------|
Intersection |--| |---| |--|
如何计算这些交叉点?
我在python中编码,但欢迎任何编程语言的答案, 因为我只需要理解算法
答案 0 :(得分:2)
第0步:为方便起见,设立Range
课程:
from collections import namedtuple
Range = namedtuple("Range", ["start", "end"])
步骤1:创建一个计算两个范围之间交点的函数。此功能适用于由两个可比较点组成的任何内容:
def intersect(range1, range2):
new_range = Range(
max(range1.start, range2.start),
min(range1.end, range2.end)
)
return new_range if new_range.start < new_range.end else None
步骤2:通过尝试所有可能的组合,创建一个能够找到两组范围的所有交点的函数。
def intersect_two(ranges1, ranges2):
for range1 in ranges1:
for range2 in ranges2:
intersection = intersect(range1, range2)
if intersection:
yield intersection
第3步:使用intersect_two
reduce()
列出一系列范围:
def intersect_all(ranges):
return reduce(intersect_two, ranges)
我使用整数来简化,但它应该与datetime
对象一样好用:
>>> timelines = [
... (Range(0, 11), Range(15, 20)),
... (Range(8, 16), Range(19, 25)),
... (Range(0, 10), Range(15, 22)),
... ]
>>>
>>> for intersection in intersect_all(timelines):
... print(intersection)
...
Range(start=8, end=10)
Range(start=15, end=16)
Range(start=19, end=20)
答案 1 :(得分:0)
我在python中进行编码,但欢迎任何编程语言的答案,因为我只需要理解算法
如果你只想要伪代码,一种算法就是:
intersections = total_range
for timeline in timelines:
intersections = intersection(timeline,intersections)
为了实现交叉路口,有几种不同的方法。一种是使用set函数,虽然你必须转换为集合,然后如果你不想要一个集合作为输出,你必须转换回来:intersections = intersections.intersection(timeline)
。另一种方法是列表理解:intersections = [time_point for time_point in intersections if time_point in timeline]
答案 2 :(得分:0)
这是我对@Felk的答案的实现:
from functools import reduce
from psycopg2.extras import DateTimeTZRange
def _DateTimeTZRange_intersect(range1, range2):
new_range = DateTimeTZRange(
max(range1.lower, range2.lower),
min(range1.upper, range2.upper)
)
return new_range if new_range.lower < new_range.upper else None
def DateTimeTZRange_intersect(*args):
return reduce(_DateTimeTZRange_intersect, args) if args else []
def _DateTimeTZRange_intersect_2d(ranges1, ranges2):
for range1 in ranges1:
for range2 in ranges2:
intersection = DateTimeTZRange_intersect(range1, range2)
if intersection:
yield intersection
def DateTimeTZRange_intersect_2d(*args):
return reduce(_DateTimeTZRange_intersect_2d, args) if args else []