如何只允许部分模式进行正则表达式模糊匹配?

时间:2019-03-16 04:22:20

标签: python regex python-3.x fuzzy-search

我有一个pattern_string = 'ATAG/GAGAAGATGATG/TATA'和一个query_string = 'ATAG/AGCAAGATGATG/TATA'。这适用于以下正则表达式匹配:

r = regex.compile('(%s){e<=2}' % pattern_string)

r.match(query_string)

在这里,唯一的变化是在两个/字符之间。但是,我想将匹配的模糊性限制为仅允许在这些字符之间进行,而/范围之外的字符则保持完全匹配。

例如,pattern_string = 'ATGG/GAGAAGATGATG/TATA'query_string = 'ATAG/AGCAAGATGATG/TATA'不是匹配项,因为字符串的第一部分(ATGGATAG)确实匹配不匹配。同样,pattern_string = 'ATAG/GAGAAGATGATG/TATG'query_string = 'ATAG/AGCAAGATGATG/TATA'也不匹配,因为字符串的最后一部分(TATGTATA)不匹配。

总而言之,/(或任何分隔符)中的字符串部分应根据为正则表达式(在这种情况下为{e<=2})指定的内容进行模糊匹配。外面的字符串必须完全匹配。

如何实现?

我在想像下面的功能

ideal_function(pattern_string, query_string)

哪里

ideal_function(pattern_string = 'ATAG/GAGAAGATGATG/TATA', query_string = 'ATAG/AGCAAGATGATG/TATA')返回True ideal_function(pattern_string = 'ATGG/GAGAAGATGATG/TATA', query_string = 'ATAG/AGCAAGATGATG/TATA')返回False

对此,最有效的方法将不胜感激,我必须对超过20,000个模式字符串和超过500万个查询字符串进行组合,因此它必须尽可能高效。尽管它必须支持允许对指定的替换计数(如{s<=2}和错误计数(如{e<=2})进行模糊匹配的选项,但不一定必须是正则表达式解决方案。

1 个答案:

答案 0 :(得分:1)

您可以使用所需的ideal_function()的以下实现将模糊性限制在斜线之间的模式部分:

def ideal_function(pattern_string, query_string, fuzzy='e<=2'):
    prefix, body, suffix = pattern_string.split('/')
    r = regex.compile('%s/(%s){%s}/%s' % (prefix, body, fuzzy, suffix))
    return r.match(query_string) is not None

这里正在起作用:

>>> ideal_function('ATAG/GAGAAGATGATG/TATA', 'ATAG/AGCAAGATGATG/TATA')
True

>>> ideal_function('ATGG/GAGAAGATGATG/TATA', 'ATAG/AGCAAGATGATG/TATA')
False

>>> ideal_function('ATAG/GAGAAGATGATG/TATA', 'ATAG/AGCAAGATGATG/TATA', 'e<=1')
False

>>> ideal_function('ATAG/GAGAAGATGATG/TATA', 'ATAG/AGCAAGATGATG/TATA', 'e<=2')
True

>>> ideal_function('ATAG/GAGAAGATGATG/TATA', 'ATAG/AGCAAGATGATG/TATA', 's<=2')
False

>>> ideal_function('ATAG/GAGAAGATGATG/TATA', 'ATAG/AGCAAGATGATG/TATA', 's<=3')
True

这取决于您在模式中始终始终有三个以斜杠分隔的部分,但是由于任何更一般化的操作还需要指定哪些部分是模糊的,哪些部分是非模糊的,因此我认为这种简单的方法适合您的用例。

ideal_function()的任何版本都必须在每次调用时都创建适当的正则表达式,但这可能并不是最有效的方法(尽管您必须进行一些分析才能建立)实际对您的具体情况有多大的影响。

根据您需要的输出类型,类似这样的 might 可能更有意义:

def ideal_generator(pattern_string, all_query_strings, fuzzy='e<=2'):
    prefix, body, suffix = pattern_string.split('/')
    r = regex.compile('%s/(%s){%s}/%s' % (prefix, body, fuzzy, suffix))
    for query_string in all_query_strings:
        if r.match(query_string) is not None:
            yield query_string

...,这将产生与pattern_string匹配的所有查询字符串。