Python 如何获取多个周期的交点
Psudo代码:Python 如何获取多个周期的交点,python,algorithm,Python,Algorithm,Psudo代码: timelines = [ (range(<from>, <to>), range(<from>, <to>)), (range(<from>, <to>), range(<from>, <to>)), (range(<from>, <to>), range(<from>, <to>)), ] 如何计算这些交点
timelines = [
(range(<from>, <to>), range(<from>, <to>)),
(range(<from>, <to>), range(<from>, <to>)),
(range(<from>, <to>), range(<from>, <to>)),
]
如何计算这些交点
我用python编写代码,但欢迎用任何编程语言回答,
因为我只需要了解算法
我正在用python编写代码,但欢迎用任何编程语言回答,因为我只需要理解算法
如果您只需要伪代码,一种算法是:
intersections = total_range
for timeline in timelines:
intersections = intersection(timeline,intersections)
对于实施交叉口,有几种不同的方法。一种是使用set函数,尽管您必须转换为集合,如果您不想将集合作为输出,则必须转换回:
crossions=crossions.crossion(timeline)
。另一种方法是列表理解:crosss=[time\u point for time\u point in crosss if time\u point in timeline]
步骤0:创建一个范围
类以方便:
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
步骤3:使用“相交两个”的范围集列表:
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)
以下是我对@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 []
从functools导入reduce
从psycopg2.extras导入DateTimeTZRange
定义日期时间范围相交(范围1,范围2):
新范围=日期时间范围(
最大值(范围1.更低,范围2.更低),
最小值(范围1.上限,范围2.上限)
)
如果new_range.lower 我会考虑使用Python中的DATETIMLE模块建立日期范围,然后循环遍历这些顺序的日期列表并识别任何匹配。然后,根据没有间隔的最近日期和最不最近日期创建一个新的日期列表。您可能会从中找到有用的信息。尽管问题是根据日期/时间范围来表述的,但任何范围类型都可以进行类似的测试。在上下文中,您可能需要计算两组范围的交点,然后获取该结果并计算其与第三个范围的交点。一个简单的优化是注意,如果结果范围为空,您可以停止,因为结果也将为空。我只想要所有时间线上的周期相交的周期。我从您的psudo代码中了解到的内容可以通过set.intersection([set(r)for ranges for r in timeline])
@demux来实现,如果您插入*
:set.intersection(*[set(r)for ranges for timeline for r in ranges])
可能会起作用,但这对我来说是有效的。
>>> 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)
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 []