Вопрос-Ответ

How to find all occurrences of a substring?

Как найти все вхождения подстроки?

В Python есть string.find() и string.rfind() для получения индекса подстроки в строке.

Мне интересно, есть ли что-то вроде string.find_all(), которое может возвращать все найденные индексы (не только первый с начала или первый с конца).

Например:

string = "test test test test"

print string.find('test') # 0
print string.rfind('test') # 15

#this is the goal
print string.find_all('test') # [0,5,10,15]

Для подсчета вхождений см. раздел Подсчет количества вхождений подстроки в строке.

Переведено автоматически
Ответ 1

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

import re
[m.start() for m in re.finditer('test', 'test test test test')]
#[0, 5, 10, 15]

Если вы хотите найти перекрывающиеся совпадения, lookahead сделает это:

[m.start() for m in re.finditer('(?=tt)', 'ttt')]
#[0, 1]

Если вам нужен обратный поиск- все без перекрытий, вы можете объединить положительный и отрицательный анализ в выражение, подобное этому:

search = 'tt'
[m.start() for m in re.finditer('(?=%s)(?!.{1,%d}%s)' % (search, len(search)-1, search), 'ttt')]
#[1]

re.finditer возвращает генератор, поэтому вы могли бы изменить [] в приведенном выше на (), чтобы получить генератор вместо списка, который будет более эффективным, если вы повторяете результаты только один раз.

Ответ 2
>>> help(str.find)
Help on method_descriptor:

find(...)
S.find(sub [,start [,end]]) -> int

Таким образом, мы можем создать ее сами:

def find_all(a_str, sub):
start = 0
while True:
start = a_str.find(sub, start)
if start == -1: return
yield start
start += len(sub) # use start += 1 to find overlapping matches

list(find_all('spam spam spam spam', 'spam')) # [0, 5, 10, 15]

Никаких временных строк или регулярных выражений не требуется.

Ответ 3

Вот (очень неэффективный) способ получить все (т. е. даже перекрывающиеся) совпадения:

>>> string = "test test test test"
>>> [i for i in range(len(string)) if string.startswith('test', i)]
[0, 5, 10, 15]

Это решение также работает для вложенных слов, состоящих из нескольких слов.

s = "Find THIS SUB-WORD in this sentence with THIS SUB-WORD"
sub = "THIS SUB-WORD"
[i for i in range(len(s)) if s.startswith(sub, I)]
# [5, 41]
Ответ 4

Использование re.finditer:

import re
sentence = input("Give me a sentence ")
word = input("What word would you like to find ")
for match in re.finditer(word, sentence):
print (match.start(), match.end())

Для word = "this" и sentence = "this is a sentence this this" это даст результат:

(0, 4)
(19, 23)
(24, 28)
2023-08-19 01:33 python string