Union of multiple ranges

后端 未结 5 614
悲&欢浪女
悲&欢浪女 2020-11-27 07:28

I have these ranges:

7,10
11,13
11,15
14,20
23,39

I need to perform a union of the overlapping ranges to give ranges that are not overlappi

5条回答
  •  暗喜
    暗喜 (楼主)
    2020-11-27 07:41

    Here is a one-liner using functools.reduce (assuming (x, 10) and (11, y) overlap):

    reduce(
        lambda acc, el: acc[:-1:] + [(min(*acc[-1], *el), max(*acc[-1], *el))]
            if acc[-1][1] >= el[0] - 1
            else acc + [el],
        ranges[1::],
        ranges[0:1]
    )
    

    This begins with the first range and uses reduce to go through the rest of the ranges. It compares the last element (acc[-1]) with the next range (el). If they overlap, it replaces the last element with the min and max of the two ranges (acc[:-1:] + [min, max]). If they don't overlap, it simply puts this new range at the end of the list (acc + [el]).

    Example:

    from functools import reduce
    
    example_ranges = [(7, 10), (11, 13), (11, 15), (14, 20), (23, 39)]
    
    def combine_overlaps(ranges):
        return reduce(
            lambda acc, el: acc[:-1:] + [(min(*acc[-1], *el), max(*acc[-1], *el))]
                if acc[-1][1] >= el[0] - 1
                else acc + [el],
            ranges[1::],
            ranges[0:1],
        )
    
    print(combine_overlaps(example_ranges))
    

    Output:

    [(7, 20), (23, 39)]
    

提交回复
热议问题