如何获得多个时期的交叉点

时间:2017-11-06 16:30:56

标签: python algorithm

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中编码,但欢迎任何编程语言的答案, 因为我只需要理解算法

3 个答案:

答案 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 []