如何使用difflib.SequenceMatcher获得多个匹配项?

时间:2015-02-25 10:24:07

标签: python regex difflib

我使用difflib来识别较长序列中短字符串的所有匹配项。但是,当有多个匹配时,difflib似乎只返回一个:

> sm = difflib.SequenceMatcher(None, a='ACT', b='ACTGACT')
> sm.get_matching_blocks()
[Match(a=0, b=0, size=3), Match(a=3, b=7, size=0)]

我预期的输出是:

[Match(a=0, b=0, size=3), Match(a=0, b=4, size=3), Match(a=3, b=7, size=0)]

实际上,字符串ACTGACT包含两个ACT匹配,位于0和4位,大小均为3(在字符串末尾加上另一个大小为0的匹配)。

如何获得多场比赛?我期待difflib返回两个位置。

2 个答案:

答案 0 :(得分:2)

为什么要使用difflib?您应该只能使用标准的正则表达式。

import re
pattern = "ACT"
text = "ACTGACT"
matches = [m.span() for m in re.finditer(pattern, text)]

会给你:

[(0, 3), (4, 7)]

或者出于某种原因,这是否包含您感兴趣的信息?它当然不会返回difflib返回的最后一个空匹配,但您可以轻松地创建它。

答案 1 :(得分:2)

正如Jerry所指出的,并且k-nut正确回答,你使用了错误的算法来解决你的问题。 老实说k-nut的答案并不是那么糟糕,但它并不是解决这类问题最有效的方法。 我是一名生物信息学家并且给出了您的问题和示例案例,看起来非常像您正试图解决“我们的”经典DNA序列比对/搜索问题(请参阅Altschul等科学超级明星的scientific literature或“如果你对这个细节很感兴趣并希望阅读有史以来被引用次数最多的论文之一的基因“迈尔斯问题。”

有效地在长段数据库中查找短段正是Altschul现在着名的BLAST算法解决启发式和/或可以使用Smith-Waterman完成的确切的查找。 在Python中执行此操作的最有效方法可能是使用BioPython,特别是,您可能希望查看描述如何设置local NCBI BLAST+ instance的部分。 如果你没有与Python“结婚”,那么今天BLAST的实现速度更快,比如FSA-BLAST

另一方面,如果你需要完全匹配(而不是BLAST所做的启发式),如果你不介意长查询时间并且有一个小参考,则可能就是这种情况序列(示例中为B),您可以使用官方的Smith-Waterman(SW)对齐方式。如果没有,并且您仍需要完全匹配,则首先过滤与BLAST匹配,然后使用候选人的SW对齐减少您的设置。

可以在纯Python中实现SW,甚至只使用任何现有的纯Python实现,但我只推荐这条路径用于纯粹的教育目的(在GitHub上查看swalign,例如)。如果你想要一个相当强大的基于Python的实现,请检查scikit-bio的SW对齐,尽管scikit-bio仍处于alpha状态。但首先要阅读上面已经链接的SW WikiPedia page,根据您拥有的硬件,您可能会在CUDAC++中使用GPU或至少SIMD优化的实施。如果你想要一个带有Python包装器的漂亮版本,请查看SSWlib