Поиск нескольких вхождений строки в строке в Python - PullRequest
60 голосов
/ 06 октября 2010

Как найти несколько вхождений строки в строке в Python?Учтите это:

>>> text = "Allowed Hello Hollow"
>>> text.find("ll")
1
>>> 

Итак, первое вхождение ll соответствует 1, как и ожидалось.Как мне найти следующее вхождение?

Тот же вопрос действителен для списка.Подумайте:

>>> x = ['ll', 'ok', 'll']

Как мне найти все ll с их индексами?

Ответы [ 16 ]

96 голосов
/ 06 октября 2010

Используя регулярные выражения, вы можете использовать re.finditer, чтобы найти все (не перекрывающиеся) вхождения:

>>> import re
>>> text = 'Allowed Hello Hollow'
>>> for m in re.finditer('ll', text):
         print('ll found', m.start(), m.end())

ll found 1 3
ll found 10 12
ll found 16 18

В качестве альтернативы, если вы не хотите использовать служебные данные обычногоВы также можете многократно использовать str.find для получения индекса next :

>>> text = 'Allowed Hello Hollow'
>>> index = 0
>>> while index < len(text):
        index = text.find('ll', index)
        if index == -1:
            break
        print('ll found at', index)
        index += 2 # +2 because len('ll') == 2

ll found at  1
ll found at  10
ll found at  16

Это также работает для списков и других последовательностей.

22 голосов
/ 06 октября 2010

Я думаю, что вы ищете string.count

"Allowed Hello Hollow".count('ll')
>>> 3

Надеюсь, это поможет
ПРИМЕЧАНИЕ: это только захватывает непересекающиеся события

19 голосов
/ 06 октября 2010

Для примера списка используйте понимание:

>>> l = ['ll', 'xx', 'll']
>>> print [n for (n, e) in enumerate(l) if e == 'll']
[0, 2]

Аналогично для строк:

>>> text = "Allowed Hello Hollow"
>>> print [n for n in xrange(len(text)) if text.find('ll', n) == n]
[1, 10, 16]

это будет перечислять смежные прогоны "ll", которые могут быть или не быть тем, что вы хотите:

>>> text = 'Alllowed Hello Holllow'
>>> print [n for n in xrange(len(text)) if text.find('ll', n) == n]
[1, 2, 11, 17, 18]
12 голосов
/ 06 октября 2010

FWIW, вот пара не-RE альтернатив, которые, как мне кажется, лучше, чем решение poke .

В первом используется str.index и проверка на ValueError:

def findall(sub, string):
    """
    >>> text = "Allowed Hello Hollow"
    >>> tuple(findall('ll', text))
    (1, 10, 16)
    """
    index = 0 - len(sub)
    try:
        while True:
            index = string.index(sub, index + len(sub))
            yield index
    except ValueError:
        pass

Во втором тесте используется str.find и выполняется проверка для часового -1 с помощью iter:

def findall_iter(sub, string):
    """
    >>> text = "Allowed Hello Hollow"
    >>> tuple(findall_iter('ll', text))
    (1, 10, 16)
    """
    def next_index(length):
        index = 0 - length
        while True:
            index = string.find(sub, index + length)
            yield index
    return iter(next_index(len(sub)).next, -1)

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

def findall_each(findall, sub, strings):
    """
    >>> texts = ("fail", "dolly the llama", "Hello", "Hollow", "not ok")
    >>> list(findall_each(findall, 'll', texts))
    [(), (2, 10), (2,), (2,), ()]
    >>> texts = ("parallellized", "illegally", "dillydallying", "hillbillies")
    >>> list(findall_each(findall_iter, 'll', texts))
    [(4, 7), (1, 6), (2, 7), (2, 6)]
    """
    return (tuple(findall(sub, string)) for string in strings)
3 голосов
/ 06 октября 2010

Для вашего примера списка:

In [1]: x = ['ll','ok','ll']

In [2]: for idx, value in enumerate(x):
   ...:     if value == 'll':
   ...:         print idx, value       
0 ll
2 ll

Если вы хотите, чтобы все элементы в списке, которые содержали 'll', вы могли бы также сделать это.

In [3]: x = ['Allowed','Hello','World','Hollow']

In [4]: for idx, value in enumerate(x):
   ...:     if 'll' in value:
   ...:         print idx, value
   ...:         
   ...:         
0 Allowed
1 Hello
3 Hollow
2 голосов
/ 06 октября 2010
>>> for n,c in enumerate(text):
...   try:
...     if c+text[n+1] == "ll": print n
...   except: pass
...
1
10
16
1 голос
/ 04 июня 2012

Совершенно новый для программирования в целом и работы через онлайн-учебник.Меня также попросили сделать это, но только с использованием методов, которые я изучил до сих пор (в основном строки и циклы).Не уверен, добавляет ли это здесь какую-либо ценность, и я знаю, что это не то, как вы бы это сделали, но я заставил его работать с этим:

0 голосов
/ 22 июля 2018

Я случайно получил эту идею недавно.Использование цикла While с объединением строк и поиском строк может работать даже для перекрывающихся строк.

findin = "algorithm alma mater alison alternation alpines"
search = "al"
inx = 0
num_str = 0

while True:
    inx = findin.find(search)
    if inx == -1: #breaks before adding 1 to number of string
        break
    inx = inx + 1
    findin = findin[inx:] #to splice the 'unsearched' part of the string
    num_str = num_str + 1 #counts no. of string

if num_str != 0:
    print("There are ",num_str," ",search," in your string.")
else:
    print("There are no ",search," in your string.")

Я - любитель программирования на Python (программирование любого языка, на самом деле) и не уверен, что другоепроблемы, которые могут возникнуть, но я думаю, что он работает нормально?

Я думаю, что lower () может быть использован где-то в нем, если это необходимо.

0 голосов
/ 05 ноября 2017

Вы также можете сделать это с условным пониманием списка следующим образом:

string1= "Allowed Hello Hollow"
string2= "ll"
print [num for num in xrange(len(string1)-len(string2)+1) if string1[num:num+len(string2)]==string2]
# [1, 10, 16]
0 голосов
/ 31 августа 2017

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

    >>> text = 'Allowed Hello Hollow'
    >>> place = 0
    >>> while text.find('ll', place) != -1:
            print('ll found at', text.find('ll', place))
            place = text.find('ll', place) + 2


    ll found at 1
    ll found at 10
    ll found at 16
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...