如何求多个周期的交点

2024-04-29 08:56:26 发布

您现在位置:Python中文网/ 问答频道 /正文

Psudo代码:

timelines = [
    (range(<from>, <to>), range(<from>, <to>)),
    (range(<from>, <to>), range(<from>, <to>)),
    (range(<from>, <to>), range(<from>, <to>)),
]

<from><to>表示日期时间对象

此“图片”在“交集”之后显示了我需要计算的值:

^{pr2}$

如何计算这些交叉口?在

我用python编写代码,但是欢迎用任何编程语言来回答, 因为我只需要理解算法


Tags: to对象代码from算法时间图片range
3条回答

步骤0:为方便起见,创建一个Range类:

from collections import namedtuple
Range = namedtuple("Range", ["start", "end"])

步骤1:创建一个计算两个范围的交集的函数。此函数适用于包含两个可比较点的任何对象:

^{pr2}$

第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的范围集列表:

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)

I'm coding in python, but answers in any programming language are welcome, as I only need to understand the algorithm

如果只需要伪代码,一种算法是:

intersections = total_range
for timeline in timelines:
    intersections = intersection(timeline,intersections)

对于实现交叉口,有几种不同的方法。一种方法是使用set函数,尽管必须转换为set,如果不希望将set作为输出,则必须将其转换回:intersections = intersections.intersection(timeline)。另一种方法是列表理解:intersections = [time_point for time_point in intersections if time_point in timeline]

以下是我对@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 []

相关问题 更多 >