当前位置:   article > 正文

【Python】使用bisect解决段落分割,快速找到所属分段_python数据分割成段

python数据分割成段

一、概念:什么是bisect?

bisect实质上是python自带的数组二分查找算法:bisect — 数组二分查找算法【官方文档】
因为本质是二分,所以需满足数组是【有序的】
以下是二分的内置算法:

def index(a, x):
    'Locate the leftmost value exactly equal to x'
    i = bisect_left(a, x)
    if i != len(a) and a[i] == x:
        return i
    raise ValueError

def find_lt(a, x):
    'Find rightmost value less than x'
    i = bisect_left(a, x)
    if i:
        return a[i-1]
    raise ValueError

def find_le(a, x):
    'Find rightmost value less than or equal to x'
    i = bisect_right(a, x)
    if i:
        return a[i-1]
    raise ValueError

def find_gt(a, x):
    'Find leftmost value greater than x'
    i = bisect_right(a, x)
    if i != len(a):
        return a[i]
    raise ValueError

def find_ge(a, x):
    'Find leftmost item greater than or equal to x'
    i = bisect_left(a, x)
    if i != len(a):
        return a[i]
    raise ValueError
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34

二、基础段落分割案例

官方给出的案例:
bisect() 函数对于数字表查询也是适用的。 这个例子使用 bisect() 根据一组有序的数字划分点来查找考试成绩对应的字母等级: (如) 90 及以上为 ‘A’,80 至 89 为 ‘B’,依此类推:

>>>def grade(score, breakpoints=[60, 70, 80, 90], grades='FDCBA'):
       i = bisect(breakpoints, score)
       return grades[i]

>>>[grade(score) for score in [33, 99, 77, 70, 89, 90, 100]]
   ['F', 'A', 'C', 'C', 'B', 'A', 'A']
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

三、实用案例

问题描述:
每天白班是6:45-18:45夜班是18:45-次日6:45
给出当前时间班次和上一班次的开始时间和结束时间

不采用bisect,使用if和else需要考虑0点到6点的情况,单独增加判断,代码if-else分支较多,代码逻辑比较冗余:

def get_shift_times(turn: int) -> TurnTimeVo:
    current_time = datetime.now()
    today = current_time.date()
    yesterday = today - timedelta(days=1)
    tomorrow = today + timedelta(days=1)
    # 一天开始的时间
    today_start_time = datetime.strptime(Constants.TODAY_START_TIME, "%H:%M:%S").time()
    # 白班开始时间
    day_start = datetime.strptime(Constants.WORK_SHIFT_START_TIME, "%H:%M:%S").time()
    # 白班结束时间
    day_end = datetime.strptime(Constants.WORK_SHIFT_END_TIME, "%H:%M:%S").time()
    # 时间段分割
    today_start = datetime.combine(today, today_start_time)
    today_day_start = datetime.combine(today, day_start)
    today_day_end = datetime.combine(today, day_end)
    yesterday_day_start = datetime.combine(yesterday, day_start)
    yesterday_day_end = datetime.combine(yesterday, day_end)
    tomorrow_day_start = datetime.combine(tomorrow, day_start)

    if turn == TurnShift.now_turn:  # 当前班次
        if current_time >= today_start and current_time <= today_day_start:
            shift_start = yesterday_day_end
            shift_end = today_day_start
        elif current_time > today_day_start or current_time <= today_day_end:
            shift_start = today_day_start
            shift_end = today_day_end
        else:
            shift_start = today_day_end
            shift_end = tomorrow_day_start
    elif turn == TurnShift.last_turn:  # 上一班次
        if current_time >= today_start and current_time <= today_day_start:
            shift_start = yesterday_day_start
            shift_end = yesterday_day_end
        elif current_time > today_day_start or current_time <= today_day_end:
            shift_start = yesterday_day_end
            shift_end = today_day_start
        else:
            shift_start = today_day_start
            shift_end = today_day_end
    else:
        raise ValueError("Invalid turn value. Please provide 1 or 2.")
    vo = TurnTimeVo(start_time=shift_start, end_time=shift_end)
    return vo
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43

采用bisect之后逻辑更为清晰:

def get_shift_times(turn: int) -> TurnTimeVo:
    current_time = datetime.now()
    today = current_time.date()
    yesterday = today - timedelta(days=1)
    tomorrow = today + timedelta(days=1)
    # 白班开始时间
    day_start = datetime.strptime(Constants.WORK_SHIFT_START_TIME, "%H:%M:%S").time()
    # 白班结束时间
    day_end = datetime.strptime(Constants.WORK_SHIFT_END_TIME, "%H:%M:%S").time()
    # 时间段分割
    today_day_start = datetime.combine(today, day_start)
    today_day_end = datetime.combine(today, day_end)
    yesterday_day_start = datetime.combine(yesterday, day_start)
    yesterday_day_end = datetime.combine(yesterday, day_end)
    tomorrow_day_start = datetime.combine(tomorrow, day_start)

    brakpoints = [
        yesterday_day_start,
        yesterday_day_end,
        today_day_start,
        today_day_end,
        tomorrow_day_start,
    ]
    current_interval_index = bisect.bisect(brakpoints, current_time)

    if turn == TurnShift.now_turn:  # 当前班次
        shift_start = brakpoints[current_interval_index - 1]
        shift_end = brakpoints[current_interval_index]
    elif turn == TurnShift.last_turn:  # 上一班次
        shift_start = brakpoints[current_interval_index - 2]
        shift_end = brakpoints[current_interval_index - 1]
    else:
        raise ValueError("Invalid turn value. Please provide 1 or 2.")

    vo = TurnTimeVo(start_time=shift_start, end_time=shift_end)
    return vo
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小小林熬夜学编程/article/detail/733150
推荐阅读
相关标签
  

闽ICP备14008679号