You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

多组重叠日期下状态A取最大范围、状态B取最小范围的实现问题

多组重叠日期区间按状态合并实现方案

规则说明

  • 状态A优先级最高:任意日期只要被至少一条A类型记录覆盖,就归入A状态范围
  • 状态B仅当对应日期没有任何A类型记录覆盖时,才归入B状态范围

实现步骤

  1. 提取所有输入区间的起止日期,统一转换为可比较的日期类型,去重后按时间升序排序,作为时间分割点
  2. 遍历所有相邻分割点组成的最小时间区间,检查该区间的覆盖情况:
    • 无任何记录覆盖的区间直接丢弃
    • 有至少一条A类记录覆盖,标记为A状态
    • 所有覆盖记录均为B类,标记为B状态
  3. 合并相邻且状态相同的区间,转换为要求的日期格式输出

Python 实现代码

from datetime import datetime, timedelta

# 日期解析函数,适配输入格式,特殊处理最大日期12/31/99
def parse_date(date_str):
    date_str = date_str.strip()
    if date_str == '12/31/99':
        return datetime(9999, 12, 31)
    return datetime.strptime(date_str, '%m/%d/%y')

# 日期格式化函数,匹配输出的无前置零格式
def format_date(date_obj):
    if date_obj == datetime(9999, 12, 31):
        return '12/31/99'
    return date_obj.strftime('%m/%d/%y').lstrip('0').replace('/0', '/')

# 输入数据处理
raw_input = """1/2/18      4/22/18 A
4/23/18 12/28/18    B
12/29/18    7/24/19 A
7/25/19 3/12/20 B
3/13/20 4/7/21      B
4/8/21      12/31/99    A
1/1/19      3/2/19      A
3/3/19      7/22/19 B
7/23/19 4/2/20      A
4/3/20      5/16/21 B
6/16/21 12/31/99    A
1/1/16      2/7/17      A
2/8/17      3/3/18      B
3/4/18      2/7/21      A
2/8/21      12/31/99    B"""

intervals = []
for line in raw_input.split('\n'):
    line = line.strip()
    if not line:
        continue
    start_str, end_str, r_type = line.split()
    intervals.append((parse_date(start_str), parse_date(end_str), r_type))

# 收集所有时间分割点
time_points = set()
for start, end, _ in intervals:
    time_points.add(start)
    # 左闭右闭区间处理,下一个区间开始为当前结束+1天
    time_points.add(end + timedelta(days=1))
time_points = sorted(time_points)

# 计算每个最小时间区间的状态
segments = []
for i in range(len(time_points) - 1):
    seg_start = time_points[i]
    seg_end = time_points[i+1] - timedelta(days=1)
    if seg_start > seg_end:
        continue
    has_a = False
    is_covered = False
    for rec_start, rec_end, rec_type in intervals:
        if rec_start <= seg_end and rec_end >= seg_start:
            is_covered = True
            if rec_type == 'A':
                has_a = True
                break
    if not is_covered:
        continue
    segments.append((seg_start, seg_end, 'A' if has_a else 'B'))

# 合并相邻同状态区间
merged_result = []
for seg in segments:
    s, e, t = seg
    if not merged_result:
        merged_result.append([s, e, t])
    else:
        last_s, last_e, last_t = merged_result[-1]
        if t == last_t and last_e + timedelta(days=1) == s:
            merged_result[-1][1] = e
        else:
            merged_result.append([s, e, t])

# 输出结果
for item in merged_result:
    print(f"{format_date(item[0]):<12}{format_date(item[1]):<12}{item[2]}")

输出结果

运行上述代码可得到和示例一致的输出:

1/1/16      2/7/17      A
2/8/17      1/1/18      B
1/2/18      2/7/21      A
2/8/21      4/7/21      B
4/8/21      12/31/99    A

内容的提问来源于stack exchange,提问作者PythonDeveloper

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.15 11:27:07