我正在学习Python 2.x并希望解决以下问题。 需要一个函数来压缩范围
问题:给定代表范围的元组列表,压缩范围
Input : [(2,3),(4,5),(7,8),(8,10),(12,15)]
Output :[(2,5),(7,10),(12,15)]
任何指针或帮助都会很有帮助
答案 0 :(得分:0)
您可以按照下面的示例继续操作。我们的想法是处理单个区间(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)
答案 1 :(得分:0)
合并范围并不像看起来那么容易和简单。你必须注意多个输入范围的重叠,以及包含,i / e范围完全包含在另一个输入范围内。
还必须确保输入按起始值排序。
这是一个经过时间考验的解决方案:
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
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***