Подсчитать количество вхождений данной подстроки в строку

201

Как я могу посчитать, сколько раз данная подстрока присутствует в строке в Python?

Например:

>>> 'foo bar foo'.numberOfOccurrences('foo')
2
Сантош
источник
Что вы подразумеваете под "числом подстрок"? Положение подстроки? Сколько раз встречается подстрока? Что-то другое?
GreenMatt
2
Это домашнее задание? Если это так, добавьте тег «домашнее задание» к своему вопросу. Кроме того, ваш вопрос не очень понятен. Я отвечу на то, что вы, кажется, спрашиваете, но я подозреваю, что вы действительно хотите узнать что-то еще.
Джим DeLaHunt
После предыдущего комментария вы можете захотеть увидеть: python: Как найти подстроку в другой строке или Базовое индексирование повторений подстроки в строке (python) . Поскольку это, вероятно, дубликат одного из них, я голосую за закрытие.
GreenMatt
@JimDeLaHunt Для записей есть упражнение на эту тему в cscircles.cemc.uwaterloo.ca/8-remix - см. Упражнение по кодированию: подсчет подстрок .
Никос Александрис

Ответы:

335

string.count(substring), как в:

>>> "abcdabcva".count("ab")
2

Обновить:

Как указано в комментариях, это способ сделать это для непересекающихся вхождений. Если вам нужно подсчитать перекрывающиеся вхождения, вам лучше проверить ответы по адресу: « Регулярное выражение Python находит все перекрывающиеся совпадения? », Или просто проверьте мой другой ответ ниже.

jsbueno
источник
14
Как насчет этого: "GCAAAAAG".count("AAA")который дает 1, а правильный ответ - 3?
карикатурист
12
countочевидно для неперекрывающихся совпадений - что чаще всего и хочется делать. stackoverflow.com/questions/5616822/… имеет дело с перекрывающимися совпадениями - но простое, хотя и дорогое, выражение:sum("GCAAAAAGH"[i:].startswith("AAA") for i in range(len("GCAAAAAGH")))
jsbueno
Можно ли считать / искать несколько слов одновременно? как string.count (substring1, substring2)
Сушант Кулкарни,
@SushantKulkarni Нет . Хотя есть один логический способ сделать такую вещь: string.count(substring1) + string.count(substring2). Но имейте в виду, что это неэффективный метод, если подстрок много, потому что подсчет каждой подстроки требует итерации по основной строке.
Фахил
Работа @SushantKulkarni ''.join([substring1, substring2]).count(pattern)более эффективна, чем решение, предложенное выше. Я проверил, используя timeit.
Энрик Калабуйг,
24
s = 'arunununghhjj'
sb = 'nun'
results = 0
sub_len = len(sb)
for i in range(len(s)):
    if s[i:i+sub_len] == sb:
        results += 1
print results
Арун Кумар Хаттри
источник
4
Дополнительное объяснение улучшит ваш ответ.
ryanyuyu
19

В зависимости от того, что вы на самом деле имеете в виду, я предлагаю следующие решения:

  1. Вы имеете в виду список подстрок, разделенных пробелами, и хотите знать, каков номер позиции подстроки среди всех подстрок:

    s = 'sub1 sub2 sub3'
    s.split().index('sub2')
    >>> 1
  2. Вы имеете в виду символьную позицию подстроки в строке:

    s.find('sub2')
    >>> 5
  3. Вы имеете в виду (непересекающиеся) отсчетов по появлению су-Подстрока:

    s.count('sub2')
    >>> 1
    s.count('sub')
    >>> 3
Дон Вопрос
источник
Попробуйте найти 'sub' или 'su'
обоховик
Я предполагаю, что вы имеете в виду s.find("su")и удивляетесь, почему вы получаете 0? Ну, это первый индекс подстроки "su"в s. Попробуйте, "ub"и вы получите 1, попробуйте, например, "z"и вы получите, -1как в подстроке не найдено.
Дон Вопрос
Я имею в виду, что вы всегда найдете только первый индекс, но не все индексы, @ arun-kumar-khattri дал правильный ответ
obohovyk
Я рад, что @ arun-kumar-khattri дал «правильный» ответ, который вы искали. Возможно, вам стоит взглянуть на комментарии jsbueno, иногда они отвечают на вопросы, которые вы еще не задали.
Дон Вопрос
Как и для третьего подхода. Кстати, я думаю, вы должны упомянуть, что это работает для непересекающихся случаев.
Зейнаб Аббасимазар
12

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

print len(re.findall('(?=aa)','caaaab'))
3
Дипак Ядав
источник
2
может быть, вы могли бы добавить len (re.findall (f '(? = {sub_string})', 'caaaab')) для динамической вставки подстроки :)
Amresh Giri
10

Чтобы найти перекрывающиеся вхождения подстроки в строку в Python 3, этот алгоритм будет делать:

def count_substring(string,sub_string):
    l=len(sub_string)
    count=0
    for i in range(len(string)-len(sub_string)+1):
        if(string[i:i+len(sub_string)] == sub_string ):      
            count+=1
    return count  

Я сам проверил этот алгоритм, и он работал.

Бхарат Кумар Р
источник
1
Небольшой совет: вместо того, чтобы сказать «Это работает, потому что я проверил это», вы можете включить пример в онлайн-сервис, такой как repl.it, с некоторыми примерами данных.
Валентина
1
спасибо за комментарий Валентин! Это мой первый ответ здесь. Я улучшу себя от моих следующих ответов.
Бхарат Кумар Р
10

Вы можете посчитать частоту двумя способами:

  1. Использование count()в str:

    a.count(b)

  2. Или вы можете использовать:

    len(a.split(b))-1

Где aстрока и bподстрока, частота которой должна быть рассчитана.

Анудж Гупта
источник
7

Текущий лучший ответ, включающий метод, в countдействительности не учитывает перекрывающиеся вхождения и не заботится о пустых подстроках. Например:

>>> a = 'caatatab'
>>> b = 'ata'
>>> print(a.count(b)) #overlapping
1
>>>print(a.count('')) #empty string
9

Первый ответ должен быть 2не1 , если мы рассмотрим перекрывающиеся подстроки. Что касается второго ответа, лучше, если пустая подстрока возвращает 0 в качестве ответа.

Следующий код заботится об этих вещах.

def num_of_patterns(astr,pattern):
    astr, pattern = astr.strip(), pattern.strip()
    if pattern == '': return 0

    ind, count, start_flag = 0,0,0
    while True:
        try:
            if start_flag == 0:
                ind = astr.index(pattern)
                start_flag = 1
            else:
                ind += 1 + astr[ind+1:].index(pattern)
            count += 1
        except:
            break
    return count

Теперь, когда мы запустим его:

>>>num_of_patterns('caatatab', 'ata') #overlapping
2
>>>num_of_patterns('caatatab', '') #empty string
0
>>>num_of_patterns('abcdabcva','ab') #normal
2
Nuhman
источник
6

Сценарий 1: вхождение слова в предложение. например: str1 = "This is an example and is easy". Появление слова «есть». Давайтеstr2 = "is"

count = str1.count(str2)

Сценарий 2: Появление шаблона в предложении.

string = "ABCDCDC"
substring = "CDC"

def count_substring(string,sub_string):
    len1 = len(string)
    len2 = len(sub_string)
    j =0
    counter = 0
    while(j < len1):
        if(string[j] == sub_string[0]):
            if(string[j:j+len2] == sub_string):
                counter += 1
        j += 1

    return counter

Спасибо!

Амит В.В.
источник
нужна ли нам эта проверка if (string [j] == sub_string [0]):? не покрывается ли оно автоматически в последующих условиях if?
AnandViswanathan89
AnandViswanathan89, Оба, если требуются условия, if (string [j] == sub_string [0]) проверяет начальное совпадение символов в основной строке, которое должно быть выполнено для всех символов основной строки, и if (string [ j: j + len2] == sub_string) выполняет вхождение подстроки. Если это для первого случая, то для второго достаточно условия.
Амит В.В.
4

Вопрос не очень понятен, но я отвечу, что вы, на поверхности, спрашиваете.

Строка S длиной L символов, где S [1] - первый символ строки, а S [L] - последний символ, имеет следующие подстроки:

  • Нулевая строка ''. Есть один из них.
  • Для каждого значения A от 1 до L, для каждого значения B от A до L строка S [A] .. S [B] (включительно). Есть L + L-1 + L-2 + ... 1 из этих строк, в общей сложности 0,5 * L * (L + 1).
  • Обратите внимание, что второй элемент включает в себя S [1] .. S [L], то есть всю исходную строку S.

Итак, в строке длиной L. есть подстроки 0.5 * L * (L + 1) + 1. Отобразите это выражение в Python, и у вас будет количество подстрок, присутствующих в строке.

Джим ДеланХант
источник
4

Одним из способов является использование re.subn. Например, чтобы подсчитать количество вхождений 'hello'в любом сочетании случаев, вы можете сделать:

import re
_, count = re.subn(r'hello', '', astring, flags=re.I)
print('Found', count, 'occurrences of "hello"')
Евгений Ярмаш
источник
Слово для меня, спасибо. @santosh, почему бы не принять ответ?
Mawg говорит восстановить Monica
2

Я оставлю свой принятый ответ как «простой и очевидный способ сделать это» - однако это не распространяется на перекрывающиеся события. Выяснить это можно наивно, с многократной проверкой срезов - как в: sum ("GCAAAAAGH" [i:]. Начинается с ("AAA") для i в диапазоне (len ("GCAAAAAGH")))

(что дает 3) - это может быть сделано с помощью трюка с использованием регулярных выражений, как можно увидеть в регулярном выражении Python найти все перекрывающиеся совпадения? - и это также может помочь в игре в тонкий код. - Это мой счет «ручной работы» для перекрывающихся вхождений шаблонов в строке, который старается не быть чрезвычайно наивным (по крайней мере, он не создает новые строковые объекты при каждом взаимодействии):

def find_matches_overlapping(text, pattern):
    lpat = len(pattern) - 1
    matches = []
    text = array("u", text)
    pattern = array("u", pattern)
    indexes = {}
    for i in range(len(text) - lpat):
        if text[i] == pattern[0]:
            indexes[i] = -1
        for index, counter in list(indexes.items()):
            counter += 1
            if text[i] == pattern[counter]:
                if counter == lpat:
                    matches.append(index)
                    del indexes[index]
                else:
                    indexes[index] = counter
            else:
                del indexes[index]
    return matches

def count_matches(text, pattern):
    return len(find_matches_overlapping(text, pattern))
jsbueno
источник
2

Перекрывающиеся случаи:

def olpcount(string,pattern,case_sensitive=True):
    if case_sensitive != True:
        string  = string.lower()
        pattern = pattern.lower()
    l = len(pattern)
    ct = 0
    for c in range(0,len(string)):
        if string[c:c+l] == pattern:
            ct += 1
    return ct

test = 'my maaather lies over the oceaaan'
print test
print olpcount(test,'a')
print olpcount(test,'aa')
print olpcount(test,'aaa')

Полученные результаты:

my maaather lies over the oceaaan
6
4
2
fyngyrz
источник
2

Для подсчета с перекрытием мы можем использовать:

def count_substring(string, sub_string):
    count=0
    beg=0
    while(string.find(sub_string,beg)!=-1) :
        count=count+1
        beg=string.find(sub_string,beg)
        beg=beg+1
    return count

Для непересекающегося случая мы можем использовать функцию count ():

string.count(sub_string)
Дирадж Двиведи
источник
2

Как насчет строки с пониманием списка? Технически его 93 символа длиной, избавьте меня от пуризма PEP-8. Ответ regex.findall является наиболее читабельным, если он представляет собой фрагмент кода высокого уровня. Если вы создаете что-то на низком уровне и не хотите зависимостей, это довольно скудно и подло. Я даю частично совпадающий ответ. Очевидно, просто используйте счет как ответ с наибольшим количеством баллов, если нет совпадений.

def count_substring(string, sub_string):
    return len([i for i in range(len(string)) if string[i:i+len(sub_string)] == sub_string])
Райан Дайнс
источник
2

Если вы хотите подсчитать все подстроки (включая перекрытые), используйте этот метод.

import re
def count_substring(string, sub_string):
    regex = '(?='+sub_string+')'
    # print(regex)
    return len(re.findall(regex,string))
Рахул Верма
источник
1

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

string=raw_input()
sub_string=raw_input()
start=0
answer=0
length=len(string)
index=string.find(sub_string,start,length)
while index<>-1:
    start=index+1
    answer=answer+1
    index=string.find(sub_string,start,length)
print answer
Hemant
источник
0

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

for i in xrange(len(word)):
if word[:len(term)] == term:
    count += 1
word = word[1:]

print count

Где слово это слово, которое вы ищете, а термин это термин, который вы ищете

Алан Винтон
источник
0
string="abc"
mainstr="ncnabckjdjkabcxcxccccxcxcabc"
count=0
for i in range(0,len(mainstr)):
    k=0
    while(k<len(string)):
        if(string[k]==mainstr[i+k]):
            k+=1
        else:
            break   
    if(k==len(string)):
        count+=1;   
print(count)
Камран Шайк
источник
2
Может быть, вы можете уточнить, чем это решение отличается от других, есть ли особый случай, который он может решить?
mpaskov
2
Хотя этот код может ответить на вопрос, предоставление дополнительного контекста относительно того, как и / или почему он решает проблему, улучшит долгосрочную ценность ответа.
Дональд Дак
0
import re
d = [m.start() for m in re.finditer(seaching, string)] 
print (d)

Это находит количество подстрок, найденных в строке, и отображает индекс.

Бхаскар Редди К
источник
импортировать re d = [m.start () для m в re.finditer (st3, st2)] # найти количество подстрок, найденных в строке, и отобразить индексный вывод print (d)
Бхаскар Редди К
0
my_string = """Strings are amongst the most popular data types in Python. 
               We can create the strings by enclosing characters in quotes.
               Python treats single quotes the same as double quotes."""

Count = my_string.lower().strip("\n").split(" ").count("string")
Count = my_string.lower().strip("\n").split(" ").count("strings")
print("The number of occurance of word String is : " , Count)
print("The number of occurance of word Strings is : " , Count)
Виная Кумар Куреси
источник
0

Риск снижения, потому что 2+ других уже предоставили это решение. Я даже проголосовал за одного из них. Но, пожалуй, новичкам легче всего понять.

def count_substring(string, sub_string):
    slen  = len(string)
    sslen = len(sub_string)
    range_s = slen - sslen + 1
    count = 0
    for i in range(range_s):
        if (string[i:i+sslen] == sub_string):
            count += 1
    return count
BabarBaig
источник
0

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

def getStringCount(mnstr:str, sbstr:str='')->int:
    """ Assumes two inputs string giving the string and 
        substring to look for number of occurances 
        Returns the number of occurances of a given string
    """
    x = dict()
    x[sbstr] = 0
    sbstr = sbstr.strip()
    for st in mnstr.split(' '):
        if st not in [sbstr]:
            continue
        try:
            x[st]+=1
        except KeyError:
            x[st] = 1
    return x[sbstr]

s = 'foo bar foo test one two three foo bar'
getStringCount(s,'foo')
Амит Говда
источник
0

Вы можете использовать startswithметод:

def count_substring(string, sub_string):
    x = 0
    for i in range(len(string)):
        if string[i:].startswith(sub_string):
            x += 1
    return x
Тревор Маселем
источник
0

Ниже логика будет работать для всех строковых и специальных символов

def cnt_substr(inp_str, sub_str):
    inp_join_str = ''.join(inp_str.split())
    sub_join_str = ''.join(sub_str.split())

    return inp_join_str.count(sub_join_str)

print(cnt_substr("the sky is   $blue and not greenthe sky is   $blue and not green", "the sky"))
Skay
источник
0

Вот решение в Python 3 и без учета регистра:

s = 'foo bar foo'.upper()
sb = 'foo'.upper()
results = 0
sub_len = len(sb)
for i in range(len(s)):
    if s[i:i+sub_len] == sb:
        results += 1
print(results)
attachPost
источник
0
j = 0
    while i < len(string):
        sub_string_out = string[i:len(sub_string)+j]
        if sub_string == sub_string_out:
            count += 1
        i += 1
        j += 1
    return count
vengat
источник
2
В то время как все ответы приветствуются, ответы только на код, как правило, не очень хорошо объясняют предмет. Пожалуйста, добавьте некоторый контекст.
creyD
0
#counting occurence of a substring in another string (overlapping/non overlapping)
s = input('enter the main string: ')# e.g. 'bobazcbobobegbobobgbobobhaklpbobawanbobobobob'
p=input('enter the substring: ')# e.g. 'bob'

counter=0
c=0

for i in range(len(s)-len(p)+1):
    for j in range(len(p)):
        if s[i+j]==p[j]:
            if c<len(p):
                c=c+1
                if c==len(p):
                    counter+=1
                    c=0
                    break
                continue
        else:
            break
print('number of occurences of the substring in the main string is: ',counter)
Паван Кумар
источник
0
s = input('enter the main string: ')
p=input('enter the substring: ')
l=[]
for i in range(len(s)):
    l.append(s[i:i+len(p)])
print(l.count(p))
Паван Кумар
источник
0

Это делает список всех вхождений (также перекрывающихся) в строке и подсчитывает их

def num_occ(str1, str2):
    l1, l2 = len(str1), len(str2)
    return len([str1[i:i + l2] for i in range(l1 - l2 + 1) if str1[i:i + l2] == str2])

Пример:

str1 ='abcabcd'
str2 = 'bc'

создаст этот список, но сохранит только значения BOLD :

[ab, bc , ca, ab, bc , cd]

что вернется:

len([bc, bc])
Элад Л.
источник
1
Пожалуйста, подумайте над тем, чтобы добавить хотя бы какое-нибудь объяснение, как будто это ответ на вопрос
β.εηοιτ.βε
0

Вот решение, которое работает как для неперекрывающихся, так и для перекрывающихся случаев. Для пояснения: перекрывающаяся подстрока - это та, последний символ которой идентичен ее первому символу.

def substr_count(st, sub):
    # If a non-overlapping substring then just
    # use the standard string `count` method
    # to count the substring occurences
    if sub[0] != sub[-1]:
        return st.count(sub)

    # Otherwise, create a copy of the source string,
    # and starting from the index of the first occurence
    # of the substring, adjust the source string to start
    # from subsequent occurences of the substring and keep
    # keep count of these occurences
    _st = st[::]
    start = _st.index(sub)
    cnt = 0

    while start is not None:
        cnt += 1
        try:
            _st = _st[start + len(sub) - 1:]
            start = _st.index(sub)
        except (ValueError, IndexError):
            return cnt

    return cnt
MRS-qv7
источник