Python 给定表示范围的元组列表,压缩范围(编写函数)
我正在学习Python2.x,并希望解决以下问题。 需要一个函数来压缩范围 问题:给定表示范围的元组列表,压缩范围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),例
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***