Python 查找与另一个大型列表重叠/相交的大型列表的子集

Python 查找与另一个大型列表重叠/相交的大型列表的子集,python,list,Python,List,我编写了一个Python模块,通过检查列表中的项目是否与另一个列表中的项目重叠/相交来查找列表的子集。我的模块的主要部分如下所示: from collections import defaultdict 总体列表中共有1865390项(项为元组) mylist中共有608348项 mylist = [(8362677, 8363216), (8414202, 8414313), …, (14634354, 14634397)] 查找列表的子集 def mysubsets(list1, lis

我编写了一个Python模块,通过检查列表中的项目是否与另一个列表中的项目重叠/相交来查找列表的子集。我的模块的主要部分如下所示:

from collections import defaultdict
总体列表中共有1865390项(项为元组)

mylist中共有608348项

mylist = [(8362677, 8363216), (8414202, 8414313), …, (14634354, 14634397)]
查找列表的子集

def mysubsets(list1, list2):                       
    sublist = [(x, y) for x, y in list1 if x <= list2[1] and y >= list2[0]]                  
    return sublist
循环遍历mylist中的每个项目,在overalllist中找到子集并将它们放入mydict

for item in mylist:
    sublist = mysubsets(overalllist, item)
    mydict.update({item:sublist})
输出如下所示

>>> mydict
defaultdict(<type 'list'>, {(14634354, 14634397): [(14634342, 14634440)], …, (8362677, 8363216): [(8361474, 8363645), (8363182, 8363758)]})
>>mydict
defaultdict(,{(146343541463397):[(146343421463440)],…,(83626778363216):[(836147483645),(8363182,8363758)])
我的脚本可以工作,但速度非常慢(运行了大约18个小时)。我使用cProfile检查了执行时间,发现mysubsets()花费了很多时间:

ncalls tottime percall cumtime percall文件名:lineno(函数)
608348 1732.827 0.003 1732.827 0.003 mymodule.py:383(mysubsets)


我想知道是否有最快捷有效的方法来实现我的目标。谢谢。

假设每个列表中的间隔在七个列表之间没有重叠,首先对每个列表进行排序,然后按照以下伪代码在线性时间内从头到尾遍历两个列表:

i1 = 0
i2 = 0
while i1<len(list1) && i2<len(list2):
  if list1[i1] is to the left of list2[i2]:
    i1 += 1
  elif list2[i2] is to the left of list1[i1]:
    i2 += 1
  else // list1[i1] overlaps list2[i2]
    find all intervals from list2[i2:] that overlap with the interval list1[i1]
    i1 += 1
i1=0
i2=0
而i1
def mysubsets(列表1、列表2):
len_l2=len(列表2)
idx=0
子列表=[]
对于列表1中的x,y:
如果x=list2[idx][1]:
附加子列表((x,y))
其他:
idx+=1
如果idx>=len_l2:
打破
返回子列表

您可以尝试的另一种方法是分而治之的方法,这并不是假设相互排斥的时间间隔:

修正一些X值

Take list1, divide it to three lists: left1, mid1, right1. 
  left1 contains all intervals that are left of x. 
  right1 contains all intervals that are right of x. 
  mid1 contains all intervals that contain x
选择值X时,应使其大致将一半的项目放在left1中,另一半放在right1中

Do the same for list2. Divide it to three lists: left2, mid2, right2.
现在我们知道left1与right2没有重叠 left2与right1没有重叠

Now, recursively find all overlaps between (left1+mid1) and (left2+mid2)
and all overlaps between (right1+mid1) and (right2+mid2)
递归的停止条件应该是其中一个列表的大小低于某个阈值


这不是一个最优算法,这里会多次发现一些重叠。但出于实际目的,应该足够快。

所以在每个列表中都有一系列的间隔,对吗?我们可以假设每个列表中的间隔之间没有重叠吗?列表排序了吗?@tglaria:我对两个列表都排序了。根据描述,列表中有重叠。酷。祝你好运,丽莎。如果你发现我的算法有错误,请告诉我,我会改正的。可能对其他人有用。我检查了我的列表,每个列表之间都有一些重叠。很抱歉。谢谢你的帮助,我将尝试你的代码并让你知道结果。这对重叠的部分(在
总体列表中
)不起作用。我在列表的子集中做了一个快速测试,脚本仍然运行得很慢。你可能想给出一些(简化的)数据示例来测试它们并评估时间。谢谢,阿迪·莱文。您的代码是用Python还是其他语言编写的?我需要一个Python代码段并将其插入到我的Python模块中。
Take list1, divide it to three lists: left1, mid1, right1. 
  left1 contains all intervals that are left of x. 
  right1 contains all intervals that are right of x. 
  mid1 contains all intervals that contain x
Do the same for list2. Divide it to three lists: left2, mid2, right2.
Now, recursively find all overlaps between (left1+mid1) and (left2+mid2)
and all overlaps between (right1+mid1) and (right2+mid2)