Функция регулярных выражений Python для подсчета повторений подстроки или разделения подстроки?

#python #regex #string #dictionary #substring

#python #регулярное выражение #строка #словарь #подстрока

Вопрос:

Я надеюсь, что вы сможете указать мне правильное направление, поскольку я новичок в программировании и Python в частности. Я пытаюсь найти максимальное количество повторений определенных подстрок в строке большего размера. Например, сколько раз 'AGATC' повторяется в гораздо более длинной строке (она может появляться только в одном месте, но четыре раза подряд в другом месте).

Я читал о регулярных выражениях для этого и написал приведенный ниже код. Она успешно распечатает повторения для каждого шаблона отдельно, однако мне нужно знать количество повторений, когда оно появится. Пример вывода моего кода выглядит следующим образом:

 ['AGATCAGATCAGATCAGATC', 'TATCTATCTATCTATCTATC', 'GAAA', 'GATA', 'AATG', 'GAAA', 'GAAA', 'GATA']
  

В этом случае 'AGATC' появляется четыре раза, но 'TATC' повторяется пять раз, поэтому мне нужно это как целое число. Если у кого-нибудь, пожалуйста, есть какие-либо идеи, чтобы продвинуть меня вперед, я был бы глубоко признателен.

Вот мой полный код:

 import re

# Opens the textfile and stores it as a string
with open('STR.txt') as strfile: 
    for row in strfile:
        STRs = row

# Defines patterns we are searching for in STR
pattern1 = (r'(?:AGATC) ')
pattern2 = (r'(?:TTTTTTCT) ')
pattern3 = (r'(?:AATG) ')
pattern4 = (r'(?:TCTAG) ')
pattern5 = (r'(?:GATA) ')
pattern6 = (r'(?:TATC) ')
pattern7 = (r'(?:GAAA) ')
pattern8 = (r'(?:TCTG) ')

# Recompiles all patterns into one single pattern
mainpattern = re.compile("(%s|%s|%s|%s|%s|%s|%s|%s)" % (pattern1, pattern2, pattern3, pattern4, pattern5, pattern6, pattern7, pattern8))

# Finds the pattern matches in STR
STR_match = re.findall(mainpattern, STRs)

print(STR_match)
  

Комментарии:

1. Если я вас правильно понимаю, вам не нужны повторяющиеся строки (например, ‘AGATCAGATCAGATCAGATCAGATC’, а вместо этого 4 одиночных совпадения), которые вы можете затем посчитать. Если это верно, вам просто нужно удалить » » из вашего шаблона поиска и проверить длину списка результатов.

2. Что-то вроде того, что мне нужно, это подсчитать количество повторений в случае ‘AGATCAGATCAGATCAGATC’, которое соответствовало бы 4, но если AGATC появится в другом месте строки, я получу 5, и это было бы неверно, поскольку мне нужно подсчитать максимальное количество повторений в любой позиции строки. К сожалению, я думаю, что удаление then может привести к неправильным результатам?

3. Ах, так вы хотите максимальное количество последовательных повторений любого из шаблонов? Например, в вашем примере 5 для TATC... части?

4. Именно это я и пытаюсь выяснить.

Ответ №1:

Если я правильно понимаю вашу проблему, вы могли бы сделать это отдельно для каждого шаблона, например, что-то вроде:

 patterns = ('AGATC', 'TTTTTTCT', 'AATG', 'TCTAG', ...)
max_len = 0
max_pattern = None
for pattern in patterns:
    match = re.findall(f'(?:{pattern}) ', STRs)
    if match:
        longest = sorted(match)[-1]  # last is the longest match
        l = len(longest)/len(pattern)
        if l > max_len:
            max_len = l
            max_pattern = pattern
print(f"{max_len} x {max_pattern}")
  

Это сопоставление вернет список всех последовательных совпадающих строк, и если вы отсортируете их в алфавитном порядке, самая длинная строка всегда будет последней, поскольку они повторяют шаблон. Затем вы можете вычислить количество повторений шаблона в этой строке.
Если вам просто нужно самое длинное повторение, вы можете вычислить максимальное из этих чисел, как показано.

Комментарии:

1. Спасибо, кажется, это возвращает правильное число (и я думаю, что я понимаю логику, стоящую за этим). Сейчас я пытаюсь изменить код, чтобы напечатать, какой шаблон был обнаружен так много раз, например, ‘AGATC’ был обнаружен 4 раза.

2. Я адаптировал код. Если вам нужны все шаблоны с максимальной длиной, вам придется немного изменить ее, но с этим вы, вероятно, сможете разобраться сами.

3. Большое вам спасибо! Я разобрался с этой версией (я изменил имя некоторых переменных): STR_name = longest[:int(len(longest)/STR_max)] Вы действительно сделали мой день, помогая мне, я действительно ценю это.