2013-09-21 4 views
3

Хорошо, так что я нашел это: Find all occurrences of a substring in PythonPython - найти все вхождения подстроки (включая перекрытие)?

Который говорит, чтобы получить индексы перекрытия мест где подстроки в списке, вы можете использовать:

[m.start() for m in re.finditer('(?=SUBSTRING)', 'STRING')]

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

[m.start() for m in re.finditer(p3, p1)]

Спасибо.

Edit:

Потому что кто-то спросил, я пойду вперед и specfify. p1 и p3 могут быть любой строкой, но если они были, например, p3 = "tryt" и p1 = "trytryt", результатом должно быть [0, 3].

+1

Пожалуйста сообщение '' p3', p1' и ожидаемый результат. –

ответ

7

Аргументы re.finditer являются простыми строками. Если у вас есть подстрока в переменной, просто отформатируйте ее в регулярное выражение. Что-то вроде '(?={0})'.format(p3) - это начало. Начиная с various symbols do have special meaning в RE вы захотите сбежать от них. К счастью, re module включает в себя re.escape для такой необходимости.

[m.start() for m in re.finditer('(?={0})'.format(re.escape(p3)), p1)] 
+0

Не работает, но я изменил '(=? {0})' назад на '(? = {0})', и он отлично работал. Благодаря! – Kevin

+0

исправлена ​​опечатка. – hop

+0

сожалеет об этом, но рад помочь. Спасибо @hop –

0

Вы делаете это (или синтаксическое варьирование):

import re 

needle = "(?=(aba))" 
haystack = "ababababa" 

[match.start() for match in re.finditer(needle, haystack)] 
#>>> [0, 2, 4, 6] 

который должен работать.

Проблема в том, что, вероятно, проблема заключается в том, что needle не имеет соответствующей формы "(? = (...))" (это видно из вашего взаимодействия с Д.Шаули). В этом случае существует несколько вариантов.

Если ваша подстрока является допустимым регулярным выражением, вы можете выполнить итерацию по возможным возможностям вручную, выполняя сопоставление.

needle = re.compile(needle) 
[i for i in range(len(haystack)) if needle.match(haystack, i)] 
#>>> [0, 2, 4, 6] 

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

needle = "aba" 
haystack = "ababababa" 

[i for i in range(len(haystack)) if haystack.startswith(needle, i)] 
#>>> [0, 2, 4, 6] 

Если вы ищете более быстрый результат , вы можете расширить цикл и использовать .index для ускорения поиска:

def findall(needle, haystack): 
    i = 0 
    try: 
     while True: 
      i = haystack.index(needle, i) 
      yield i 
      i += 1 

    except ValueError: 
     pass 

, который является самым быстрым способом я могу думать.

+0

полностью не хватает точки вопроса. также, очень запутанный. – hop

+0

Как так?Последний фрагмент - это именно то, о чем просили; первые две работы предполагают, что подстрока может быть определена как любое регулярное выражение, как подразумевается в коде вопроса. – Veedrac

+0

сначала вы переписываете код OPs без видимой причины. то: вопрос фактически спрашивает о том, как построить одну строку из другой, которую вы не адресуете. также вы пишете «что должно работать», подразумевая, что это не так, но не объясните, в каких обстоятельствах это не так. я, конечно, работает с регулярным выражением как указано, и почему это должно быть когда-либо изменено? то вы идете по касательной относительно O(), что совершенно не имеет отношения к теме. и говоря о сложности: версия регулярного выражения полностью удаляет версию strcmp из воды для более длинных стогов сена - просто 'timeit'. достаточно? – hop

1

Regex может быть излишним здесь:

>>> word = 'tryt' 
>>> text = 'trytryt' 
>>> [i for i, _ in enumerate(text) if text.startswith(word, i)] 
[0, 3] 
Смежные вопросы