Порахувати кількість входжень даної підрядки в рядку


205

Як я можу підрахувати кількість присутніх даної підрядки в рядку в Python?

Наприклад:

>>> 'foo bar foo'.numberOfOccurrences('foo')
2

Що ви маєте на увазі під "числом підрядків"? Положення підрядка? Скільки разів виникає підрядка? Щось ще?
GreenMatt

2
Це домашнє завдання? Якщо це так, будь-ласка, додайте до свого тегу "домашнє завдання". Крім того, ваше питання не дуже зрозуміло. Я відповім на те, що ви, здається, запитуєте, але я підозрюю, що ви дійсно хочете дізнатися щось інше.
Jim DeLaHunt

Після попереднього коментаря ви можете побачити: python: Як знайти підрядку в іншій рядку або Основні індексації повторень підрядки в рядку (python) . Оскільки це видається певним дублікатом одного з таких, я голосую за закриття.
GreenMatt

@JimDeLaHunt Для записів про це існує вправа в cscircles.cemc.uwaterloo.ca/8-remix - див. Вправа на кодування: Підрахунок підрядків .
Нікос Олександріс

Відповіді:


335

string.count(substring), як у:

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

Оновлення:

Як зазначалося в коментарях, це спосіб зробити це для випадків, що не перетинаються . Якщо вам потрібно порахувати збіги, що перекриваються, то краще перевірте відповіді за адресою: " Регекс Python знайде всі збіги, що перекриваються? ", Або просто перевірте іншу відповідь нижче.


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)
Sushant Kulkarni

@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
Додаткове пояснення покращить вашу відповідь.
рянюю

19

Залежно від того, що ви насправді маєте на увазі, пропоную такі рішення:

  1. Ви маєте на увазі список підрядів, розділених пробілом, і хочете знати, який номер позиції підрядків серед усіх підрядків:

    s = 'sub1 sub2 sub3'
    s.split().index('sub2')
    >>> 1
  2. Ви маєте на увазі char-положення підрядка в рядку:

    s.find('sub2')
    >>> 5
  3. Ви маєте на увазі (неперекриваються) підрахунки появи сурядного рядка:

    s.count('sub2')
    >>> 1
    s.count('sub')
    >>> 3

Спробуйте знайти "суб" або "су"
обоховик

Я думаю, ти маєш на увазі s.find("su")і цікавишся, чому ти отримуєш 0? Ну це перший індекс підрядків "su"у s. Спробуйте, "ub"і ви отримаєте 1, спробуйте, наприклад, "z"і ви отримаєте -1як у жодному підрядку не знайдено.
Дон Питання

Я маю на увазі, що ви завжди знаходите лише перший індекс, але не всі індекси, @ arun-kumar-khattri дав правильну відповідь
обоховик

Мені полегшено, що @ arun-kumar-khattri дав "правильну" відповідь, яку ви шукали. Можливо, варто додатково подивитись на коментарі jsbueno, іноді вони відповідають на питання, які ви просто ще не ставили.
Дон Питання

Як і для третього підходу. BTW, я думаю, ви повинні згадати, що це працює для випадків, що не перетинаються.
Зейнаб Аббасімазар

12

Найкращий спосіб знайти підрядку, що перекривається, у даній рядку - це використовувати регулярний вираз python, він знайде всі збіги, що перекриваються, використовуючи бібліотеку регулярних виразів. Ось як це зробити зліва - це підрядка, а в правій частині ви надасте рядок, щоб відповідати

print len(re.findall('(?=aa)','caaaab'))
3

2
можливо, ви можете додати len (re.findall (f '(? = {sub_string})', 'caaaab')), щоб динамічно вставити
підрядку

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
дякую за ваш коментар Валентин! Це моя перша відповідь тут. Я вдосконалюся від своїх наступних відповідей.
Бхарат Кумар R

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

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

Дякую!


чи справді нам потрібна ця перевірка, якщо (string [j] == sub_string [0]):? чи це автоматично не покривається в наступних випадках, якщо стан?
AnandViswanathan89

AnandViswanathan89, обидва, якщо необхідні умови, якщо (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, чому б не прийняти відповідь?
Мауг каже, що повернемо Моніку

2

Я буду зберігати свою прийняту відповідь як "простий і очевидний спосіб зробити це", однак це не охоплює випадків, що перетинаються. Дізнатися про це можна наївно, за допомогою багаторазової перевірки фрагментів - як у: sum ("GCAAAAAGH" [i:]. Startwith ("AAA") для i в межах (len ("GCAAAAAGH"))

(Що дає 3) - це може бути зроблено шляхом використання трюк регулярних виразів, як можна бачити на Python Regex знайти все, що перекриваються матчі? - і це також може призвести до тонкого коду в гольф. Це мій "ручний" підрахунок для перекриття фігур у рядку, який намагається бути не дуже наївним (принаймні, це не створює нових струнних об'єктів при кожній взаємодії):

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))

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

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

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)

Це знаходить, скільки разів знайдено підрядку в рядку та відображає індекс.


import re d = [m.start () для m в re.finditer (st3, st2)] # фіксація кількості разів, підрядних рядків, знайдених у рядку та відображення індексу print (d)
Bhaskar Reddi K

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

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

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

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"))

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)

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

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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.