Python: поиск всех вхождений подстроки в строке без использования регулярных выражений - PullRequest
0 голосов
/ 28 ноября 2018

У меня есть строка:

b = 'Can you can a can as a canner can can a can?'

Мне нужно найти все возможные начальные и конечные позиции подстроки "can" в строке b, независимо от случая.Я могу сделать это с помощью регулярного выражения, но мне нужен минимальный код для той же операции без использования регулярного выражения (или без импорта re).Вот мой код с использованием регулярных выражений:

import re
b_find = [(i.start() , i.end()) for i in re.finditer(r"can",b.lower())]

Я хочу решение без использования регулярных выражений, возможно, с использованием понимания списка.есть ли способ?

Ответы [ 4 ]

0 голосов
/ 28 ноября 2018

Это сверхпростой линейный конечный автомат.Было бы немного сложнее, если бы у вас было такое слово, как «cacan», но для «can» это действительно легко:

def nextCan( str, state ):
    for i in range(len(str)):
        ch = str[i]
        if 0 == state:
            if ch == 'c':
                state = 1
            else:
                state = 0
        elif 1 == state:
            if ch == 'a':
                state = 2
            else:
                state = 0
        elif 2 == state:
            if ch = 'n':
                yield (i-2,i+1)
            state = 0

b_find = [ x for x in nextCan( b, 0 ) ]
0 голосов
/ 28 ноября 2018

Написано как функция, это должно служить вашей цели:

>>> def split_indices(s, sep):
...     current = 0
...     sep_len = len(sep)
...     sections = s.lower().split(sep)
...     for section in sections[:-1]:  # skip trailing entry
...         current += len(section)
...         yield (current, current+sep_len)
...         current += sep_len

Функция является генератором, поэтому, если вы хотите получить результат в виде списка, вам придется либо переписатьфункция для возврата списка или распаковки результата в список:

>>> b = 'Can you can a can as a canner can can a can?'
>>> [*split_indices(b, 'can')]
[(0, 3), (8, 11), (14, 17), (23, 26), (30, 33), (34, 37), (40, 43)]
0 голосов
/ 28 ноября 2018

Еще более простой вариант:

block = 'Can you can a can as a canner can can a can?'.lower()
index = -1
indexes = []
try:
  while True:
    index = block.index('can', index + 1)
    indexes.append(index)
except ValueError:
  pass
0 голосов
/ 28 ноября 2018

Да, есть, но это не супер-элегантно и не очень эффективно. Но вот оно:

b_find = [(i, i+3) for i in range(len(b)-2) if b[i:i+3].lower() == 'can']

, и оно дает тот же результат, что и ваш regex код.То есть:

[(0, 3), (8, 11), (14, 17), (23, 26), (30, 33), (34, 37), (40, 43)]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...