如何捕捉一组最长的序列

How to catch the longest sequence of a group

任务是找到一组最长的序列

例如,给定 DNA 序列:"AGATCAGATCTTTTTTCTAATGTCTAGGATATATCAGATCAGATCAGATCAGATCAGATC" 它出现了 7 次 AGATC。 (AGATC) 匹配所有匹配项。 是否可以编写一个只捕获最长序列的正则表达式,即给定文本中的 AGATCAGATCAGATCAGATCAGATC ? 如果仅使用正则表达式这是不可能的,我如何遍历 python 中的每个序列(即第一个序列是 AGATCAGATC、第二个 - AGATCAGATCAGATCAGATCAGATC 等等)?

使用:

import re

sequence = "AGATCAGATCTTTTTTCTAATGTCTAGGATATATCAGATCAGATCAGATCAGATCAGATC"
matches = re.findall(r'(?:AGATC)+', sequence)

# To find the longest subsequence
longest = max(matches, key=len)

解释:

非捕获组(?:AGATC)+

  • + 量词——匹配一次到无限次,尽可能多。
  • AGATC 按字面匹配字符 AGATC(区分大小写)

结果:

# print(matches)
['AGATCAGATC', 'AGATCAGATCAGATCAGATCAGATC']

# print(longest)
'AGATCAGATCAGATCAGATCAGATC'

您可以测试正则表达式 here

使用re.finditer() 遍历所有匹配项。然后使用 max() 和一个键函数来找到最长的。让它成为一个函数,这样你就可以使用不同的组。

import re

def find_longest(sequence, group):
    # build pattern
    pattern = fr"(?:{group})+"

    # iterate over all matches
    matches = (match[0] for match in re.finditer(pattern, sequence))

    # find the longest
    return max(matches, key=len)

seq = "AGATCAGATCTTTTTTCTAATGTCTAGGATATATCAGATCAGATCAGATCAGATCAGATC"

find_longest(seq, "AGATC")

中心问题是,“是否可以编写一个只捕获最长序列的正则表达式?”答案是肯定的:

import re

s = 'AGATC_AGATCAGATC_AGATCAGATCAGATC_AGATC_AGATCAGATC'

m = re.search(r'((?:AGATC)+)(?!.*)', s)
print m.group() if m else ''
  #=> "AGATCAGATCAGATC"

Regex demo<¯\(ツ)>Python demo

Python 的正则表达式引擎执行以下操作。

(            begin capture group 1
  (?:AGATC)  match 'AGATC' in a non-capture group
  +          execute the non-capture group 1+ times
)            end capture group 1
(?!          begin a negative lookahead
  .*         match 0+ characters
           match the content of capture group 1
)            end the negative lookahead

对于上面的字符串 sAGATC 将首先被匹配,但否定前瞻会发现 AGATC 作为 AGATCAGATC 的第一部分,因此暂定匹配会被拒绝。然后 AGATCAGATC 将被匹配,但否定前瞻会发现 AGATCAGATC 作为 AGATCAGATCAGATC 的第一部分,因此临时匹配也将被拒绝。接下来,AGATCAGATCAGATC 将被匹配并接受,因为否定先行不会在字符串后面找到该匹配项。 (re.findallre.search 不同,它还会匹配字符串末尾的 AGATCAGATC。)

如果使用了 re.findall,最长的匹配项之后可能会有多个匹配项(请参阅正则表达式演示 link 处的最后一个测试字符串),但匹配项的长度是非从第一个到最后一个递减。因此,使用 re.search 获得的第一个匹配是最长的匹配。