Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/305.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 给定表示范围的元组列表,压缩范围(编写函数)_Python_Python 2.7 - Fatal编程技术网

Python 给定表示范围的元组列表,压缩范围(编写函数)

Python 给定表示范围的元组列表,压缩范围(编写函数),python,python-2.7,Python,Python 2.7,我正在学习Python2.x,并希望解决以下问题。 需要一个函数来压缩范围 问题:给定表示范围的元组列表,压缩范围 Input : [(2,3),(4,5),(7,8),(8,10),(12,15)] Output :[(2,5),(7,10),(12,15)] 任何指针或帮助都是非常有用的例如,您可以按照下面的示例进行操作。其思想是处理单个间隔(lb,ub),对于每个下限lb,标记增加1,而对于每个上限ub,标记减少-1。 假设整数输入,代码有效地考虑了区间(lb-0.5,ub+0.5),例

我正在学习Python2.x,并希望解决以下问题。 需要一个函数来压缩范围

问题:给定表示范围的元组列表,压缩范围

Input : [(2,3),(4,5),(7,8),(8,10),(12,15)]
Output :[(2,5),(7,10),(12,15)]

任何指针或帮助都是非常有用的

例如,您可以按照下面的示例进行操作。其思想是处理单个间隔
(lb,ub)
,对于每个下限
lb
,标记增加1,而对于每个上限
ub
,标记减少
-1
。 假设整数输入,代码有效地考虑了区间
(lb-0.5,ub+0.5)
,例如
(2,3)
(4,5)
被合并。为了避免使用浮点数作为字典键,字典
stat
存储双倍的数字

然后,当您处理这些单独的“中断”点时,总累积值(
cnt
)会告诉您当前点覆盖了多少间隔。只要这个数字大于零,我们就在一个合并段内。如果它降到零,我们可以取下一个断点并重复该过程

spec = {}
L = [(2,3),(4,12),(7,8),(8,10),(12,15)]
for lb, ub in L:
    lb, ub = min(lb, ub), max(lb, ub)
    for v in [2*lb - 1, 2*ub + 1]:
        if not v in spec: spec[v] = 0
    spec[2*lb - 1] += 1
    spec[2*ub + 1] -= 1

break_points = sorted(spec.keys())
N = len(break_points)

idx = -1
while idx < N-1:
    idx += 1

    lb, ub = break_points[idx], None
    cnt = spec[lb]

    while cnt > 0:
        idx += 1
        ub = break_points[idx]
        cnt += spec[ub]

    print((lb+1)/2, (ub-1)/2)
    #prints (2, 15)
spec={}
L=[(2,3)、(4,12)、(7,8)、(8,10)、(12,15)]
对于lb,ub在L中:
磅,磅=最小值(磅,磅),最大值(磅,磅)
对于v英寸[2*lb-1,2*ub+1]:
如果规范中没有v:spec[v]=0
规格[2*lb-1]+=1
规格[2*ub+1]-=1
断点=已排序(规范键())
N=长度(断点)
idx=-1
当idx0时:
idx+=1
ub=断点[idx]
cnt+=规格[ub]
打印((磅+1)/2,(ub-1)/2)
#印刷品(2、15)

合并范围并不像看上去那么简单和直接。您必须注意多个输入范围上的重叠,以及包含,即完全包含在另一个输入范围中的范围

还必须确保输入按起始值排序

下面是一个经过测试的解决方案:

def overlap(r1, r2):
    return r1[1] >= r2[0] - 1    # <-- -1 to ensure ranges like (2, 3) and (4, 5) merge into (2, 5)

def merge_range(r1, r2):
    s1, e1 = r1
    s2, e2 = r2
    return (min(s1, s2), max(e1, e2))

def regroup_ranges(rgs):
    assert all([s <= e for s, e in rgs])
    if len(rgs) == 0:
        return rgs

    rngs.sort()

    regrouped = [rgs[0]]

    for r2 in rgs[1:]:
        r1 = regrouped.pop()
        if overlap(r1, r2):
            regrouped.append(merge_range(r1, r2))
        else:
            regrouped.append(r1)
            regrouped.append(r2)

    return regrouped
测试结果:
“我正在学习Python2.x”说真的,只需学习3.x。Python2将被淘汰。为什么
(2,3)
(4,5)
合并成
(2,5)
?python中的范围通常不包括范围的最后一个元素。请粘贴到目前为止所做的操作。我们很乐意帮助您,但我们不会为您做家庭作业。@ReblochonMasque(2,3)和(4,5)合并为(2,5),因为它们在同一范围内。我们需要压缩ranges@gonczor很抱歉给您添麻烦,不过我是Python的新手,完全弄糊涂了。最初我想用for循环来迭代元组并比较它们(但不知何故没有找到正确的方法
def test_regroup_ranges():
    rngs = [(2, 3), (4, 5), (7, 8), (8, 10), (12, 15)]
    compressed = [(2, 5), (7, 10), (12, 15)]
    print(regroup_ranges(rngs))
    assert regroup_ranges(rngs) == compressed

    rngs = [(2, 8), (4, 5), (7, 8), (8, 10), (12, 15)]
    compressed = [(2, 10), (12, 15)]
    print(regroup_ranges(rngs))
    assert regroup_ranges(rngs) == compressed

    rngs = [(2, 3) ,(4, 5), (1, 16), (8, 10), (12, 15)]
    compressed = [(1, 16)]
    print(regroup_ranges(rngs))
    assert regroup_ranges(rngs) == compressed

    rngs = [(2, 3), (4, 20), (7, 8), (8, 10), (12, 15)]
    compressed = [(2, 20)]
    print(regroup_ranges(rngs))
    assert regroup_ranges(rngs) == compressed

    rngs = [(2, 3), (5, 8), (10, 12)]
    compressed = [(2, 3), (5, 8), (10, 12)]
    print(regroup_ranges(rngs))
    assert regroup_ranges(rngs) == compressed

    rngs = [(2, 3)]
    compressed = [(2, 3)]
    print(regroup_ranges(rngs))
    assert regroup_ranges(rngs) == compressed

    rngs = []
    compressed = []
    print(regroup_ranges(rngs))
    assert regroup_ranges(rngs) == compressed

    print("***all tests pass***")

test_regroup_ranges()
[(2, 5), (7, 10), (12, 15)]
[(2, 10), (12, 15)]
[(1, 16)]
[(2, 20)]
[(2, 3), (5, 8), (10, 12)]
[(2, 3)]
[]
***all tests pass***