我有两个包含浮点数值的排序列表。第一个(l1
)包含我感兴趣的值,而第二个列表包含我想要搜索的值(l2
)。然而,我不是在寻找完全匹配,而是容忍一定差异的值,并且我可以根据函数进行调整。由于我非常频繁地进行此搜索(>>100000),并且列表可能相当大(~5000和~200000元素),因此我真的很关心运行时效率。起初,我以为我可以通过numpy.isclose()
来解决,但我的容差并不固定,而是取决于感兴趣的值。多层嵌套的for循环可以工作,但速度非常慢。我相信有一些高效的方法来解决这个问题。
#check if two floats are close enough to match
def matching(mz1, mz2):
if abs( (1-mz1/mz2) * 1000000) <= 2:
return True
return False
#imagine another huge for loop around everything
l1 = [132.0317, 132.8677, 132.8862, 133.5852, 133.7507]
l2 = [132.0317, 132.0318, 132.8678, 132.8861, 132.8862, 133.5851999, 133.7500]
d = {i:[] for i in l1}
for i in l1:
for j in l2:
if matching(i, j):
d[i].append(j)
提示:作为匹配函数的替代方案,我也可以先创建一个字典,将l1
中感兴趣的值映射到窗口(min, max)
。例如{132.0317:(132.0314359366, 132.0319640634), ...}
,但我认为对于每个l2
中的值,检查它是否位于该字典中某个窗口内,甚至会更慢...
下面是生成包含l1每个值的最小/最大值的字典的方法:
def calcMinMaxMZ(mz, delta_ppm=2):
minmz = mz- (mz* +delta_ppm)/1000000
maxmz = mz- (mz* -delta_ppm)/1000000
return minmz, maxmz
minmax_d = {mz:calcMinMaxMZ(mz, delta_ppm=2) for mz in l1}
结果可能是这样的字典:
d = {132.0317: [132.0317, 132.0318],132.8677:[132.8678],132.8862:[132.8862, 132.8861],133.5852:[133.5851999],133.7507:[]}
但实际上,当有匹配时,我做了更多事情。感谢任何帮助!
l2
中的元素是否可能匹配到l1
中的多个元素? - StardustGogetal1
中的每个元素,在l2
中使用两个二分搜索来查找包含所有可能匹配项的子列表的起始和结束索引。对于每个列表,排序的时间复杂度为O(nlogn)
。然后,二分查找的时间复杂度为O(nlogm)
,而在范围内迭代的时间复杂度为O(nm)
(其中l1
的大小为n
,l2
的大小为m
)。总体而言,我认为l2
的排序(具有O(mlogm)
)将是限制因素。 - StardustGogeta