系统会为您提供配对列表。每对存储代表一个时间窗口的开始和结束日期。任务是验证是否存在任何重叠。
请注意,可以使用两个嵌套的for循环遍历periods
和一些if条件来验证是否不存在重叠,从而轻松解决该问题。但是,我很想看看是否有一个更具可读性和优雅的解决方案,该解决方案可以使循环保持不变,并且if语句的数量最少,并且不一定使用标准库。
相邻条目之间不一定发生重叠。
列表periods
的时间窗口少于10个。我不关心CPU时间。我担心代码的可读性。
from datetime import datetime
overlapping_periods = [
[datetime(2019, 1, 1), datetime(2019, 1, 5)],
[datetime(2019, 1, 6), datetime(2019, 1, 10)],
[datetime(2019, 1, 9), datetime(2019, 1, 15)],
]
non_overlapping_periods = [
[datetime(2019, 1, 1), datetime(2019, 1, 5)],
[datetime(2019, 1, 6), datetime(2019, 1, 10)],
[datetime(2019, 1, 11), datetime(2019, 1, 15)],
]
# Find an elegant `verify_overlaps`.
verify_overlaps(overlapping_periods) # True
verify_overlaps(non_overlapping_periods) # False
答案 0 :(得分:0)
是这么简单,还是我错过了什么?
def verify_overlaps(s):
s = sorted(s) # sorts on first member of each element by default
current = datetime.min
for dt0, dt1 in s:
if dt0 <= current:
return False
current = dt1
return True
您没有指定一个周期的开始与另一个周期的结束是否被视为重叠。只需“ <” vs“ <=”。
答案 1 :(得分:0)
您可以使用sorted
函数,该函数返回一个可迭代的对象(默认情况下,它将按列表中的第一个参数排序):
def verify_overlap(periods):
d2_previous = datetime(1900,1,1)
for d1, d2 in (sorted(periods)):
if d1 <= d2_previous:
return False
d2_previous = d2
return True
答案 2 :(得分:0)
我不知道您是否认为这更具可读性,但是:
import itertools
from typing import NamedTuple
class Period(NamedTuple):
start: datetime
end: datetime
def __and__(self, other):
return (
other.start in self or
self.start in other
)
def __contains__(self, dt):
return dt >= self.start and dt < self.end
def pairwise(iterable):
a, b = itertools.tee(iterable)
next(b, None)
return zip(a, b)
def verify_overlaps(periods):
return any(a & b for a, b in pairwise(sorted(periods)))