Python:优化区间之间的成对重叠

标签 python intervals

我有很多间隔(大约 5k 到 10k)。这些元素有开始和结束位置;像 (203, 405)。间隔的坐标存储在列表中。

我想确定每对间隔之间重叠部分的坐标和长度。这可以按如下方式完成:

# a small list for clarity, with length normally around 5000s
cList = ((20, 54), (25, 48), (67, 133), (90,152), (140,211), (190,230)) 
for i, c1 in enumerate(cList[:-1]): # a linear pairwise combination
    for c2 in cList[i + 1:]:
        left =  max(c1[0], c2[0])
        right = min(c1[1], c2[1])
        overlap = right - left
        if overlap > 0:
            print "left: %s, right: %s, length: %s" % (left, right, overlap)

导致:

left: 25, right: 48, length: 23
left: 90, right: 133, length: 43
left: 140, right: 152, length: 12
left: 190, right: 211, length: 21

可以看出,它有效...因为这可能需要相当长的时间(20 秒)我的问题是,我将如何优化它?当第二个循环的起始位置超过第一个结束位置时,我试图切断第二个for循环:

if c1[1] < c2[0]:
    break

这大大减少了程序时间,但由此产生的重叠次数比以前少了大约三倍,因此结果肯定是无效的。这是由长度比前面的元素大得多的元素引起的。

我确信有一些数学技巧可以解决这个问题

最佳答案

通常,如果您按起点对区间进行排序,这类问题会变得容易得多。

首先,让我们定义一个函数,为了让事情更清楚:

def overlap( r1, r2 ):
    left =  max(r1[0], r2[0])
    right = min(r1[1], r2[1])
    over = right - left
    return (left, right, over) if over>0 else None

您描述的算法可以写成:

for i, c1 in enumerate(cList[:-1]): 
    for c2 in cList[i + 1:]:
        o = overlap(c1,c2)
        if not o is None:
            print "left: %s, right: %s, length: %s" % o

如果您对元素进行排序,您可以在找到不重叠的部分后立即“短路”,因为您知道列表中更远的部分将更“远离”:

l= sorted(cList)
for i, c1 in enumerate(l[:-1]): 
    for c2 in l[i + 1:]:
        o= overlap(c1,c2)
        if o is None:
            break
        print "left: %s, right: %s, length: %s" % o

当然,如果您的输入已经排序(看起来),您可以跳过该步骤。

请注意,一般来说,您可以使用更清晰的 itertools.combinations 而不是使用双 for .它保证相同类型的排序。不幸的是,它不适合算法的优化版本,但你的可以写成

from itertools import combinations
for c1,c2 in combinations(cList, 2):
    o= overlap(c1,c2)
    if not o is None:
        print "left: %s, right: %s, length: %s" % o

最后,如果您想要在间隔上执行快速通用操作,您可能还需要考虑使用 Interval Tree数据结构。有 a python implementation on pypi .

关于Python:优化区间之间的成对重叠,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23218551/

相关文章:

python - python CSV 和 JSON 文件的编码/解码故障排除

python - django 1.9 中的 from django.views.generic.simple import direct_to_template 的等价物是什么

C++ 在一组区间内有效搜索值

c - 如何在c中生成设定范围内具有均匀间隔的随机值

python - Django 数据库路由器无法导入名称连接

python - 来自变量的 Pymysql 表名

python - 是否有任何资源可以让 Python 2.7 开发人员跟上 Python 3.3 的速度?

android - 在自定义 ListView 中更新 TextView

ios - 设置 UIProgressView 的最大值(swift 4)

mysql - 条件查询获取两个日期之间有间隔的数据