Contare il numero di occorrenze di una determinata sottostringa in una stringa


201

Come posso contare il numero di volte in cui una determinata sottostringa è presente all'interno di una stringa in Python?

Per esempio:

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

Cosa intendi per "numero di sottostringa"? La posizione della sottostringa? Quante volte si verifica la sottostringa? Qualcos'altro?
GreenMatt,

2
È un compito a casa? In tal caso, aggiungi il tag "compiti a casa" alla tua domanda. Inoltre, la tua domanda non è molto chiara. Risponderò a quello che sembra stia chiedendo, ma sospetto che tu voglia davvero scoprire qualcos'altro.
Jim DeLaHunt

Dopo il commento precedente, potresti voler vedere: python: come trovare una sottostringa in un'altra stringa o ricorrenze di indicizzazione di base di una sottostringa all'interno di una stringa (python) . Dato che questo sembra un probabile duplicato di uno di quelli, sto votando per chiudere.
GreenMatt,

@JimDeLaHunt Per la cronaca, c'è un esercizio al riguardo in cscircles.cemc.uwaterloo.ca/8-remix - vedi Esercizio di codifica: conteggio dei substrati .
Nikos Alexandris,

2
Possibile duplicato delle ricorrenze dell'indicizzazione
Valentin,

Risposte:


335

string.count(substring), come in:

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

Aggiornare:

Come sottolineato nei commenti, questo è il modo di farlo per occorrenze non sovrapposte . Se hai bisogno di contare le occorrenze sovrapposte, è meglio controllare le risposte su: " Python regex trova tutte le corrispondenze sovrapposte? ", Oppure controlla la mia altra risposta di seguito.


14
Che dire di questo: "GCAAAAAG".count("AAA")che dà 1, mentre la risposta corretta è 3?
vignettista

12
countè ovviamente per le partite non sovrapposte, che è spesso ciò che si vuole fare. stackoverflow.com/questions/5616822/… si occupa di partite sovrapposte, ma un'espressione semplice, seppur costosa, è:sum("GCAAAAAGH"[i:].startswith("AAA") for i in range(len("GCAAAAAGH")))
jsbueno,

È possibile contare / cercare più parole contemporaneamente? come string.count (substring1, substring2)
Sushant Kulkarni

@SushantKulkarni No. Anche se c'è un modo logico di fare un cosa del genere: string.count(substring1) + string.count(substring2). Ma tieni presente che questo non è un metodo efficiente se ci sono molte sottostringhe perché il conteggio di ogni sottostringa richiede un'iterazione sulla stringa principale.
Faheel

Fare @SushantKulkarni ''.join([substring1, substring2]).count(pattern)è più efficiente della soluzione suggerita sopra. Ho controllato usando timeit.
Enric Calabuig,

23
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
Ulteriori spiegazioni migliorerebbero la tua risposta.
Ryanuyu,

19

A seconda di cosa intendi veramente, propongo le seguenti soluzioni:

  1. Intendi un elenco di sottostringhe separate da spazio e vuoi sapere qual è il numero di posizione della sottostringa tra tutte le sottostringhe:

    s = 'sub1 sub2 sub3'
    s.split().index('sub2')
    >>> 1
  2. Intendi la posizione char della sottostringa nella stringa:

    s.find('sub2')
    >>> 5
  3. Intendi i conteggi (non sovrapposti) dell'aspetto di una stringa secondaria:

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

Prova a trovare 'sub' o 'su'
obohovyk

Immagino che tu intenda s.find("su")e mi chiedo perché lo ottieni 0? Bene, questo è il primo indice della sottostringa "su"in s. Prova "ub"e otterrai 1, prova ad esempio "z"e otterrai -1come in nessuna sottostringa trovata.
Don Domanda

Voglio dire che trovi sempre solo il primo indice, ma non tutti gli indici, @ arun-kumar-khattri ha dato la risposta corretta
obohovyk

Sono sollevato che @ arun-kumar-khattri abbia dato la risposta "corretta" che stavi cercando. Forse dovresti dare un'occhiata ai commenti di jsbueno, a volte rispondono a domande che non hai ancora fatto.
Domanda Don

Come per il terzo approccio. A proposito, penso che dovresti menzionare che funziona per casi non sovrapposti.
Zeinab Abbasimazar,

12

Il modo migliore per trovare una sottostringa sovrapposta in una data stringa è usare l'espressione regolare python che troverà tutte le corrispondenze sovrapposte usando la libreria di espressioni regolari. Ecco come farlo a sinistra è la sottostringa e a destra fornirai la stringa da abbinare

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

2
forse potresti aggiungere len (re.findall (f '(? = {sub_string})', 'caaaab')) per inserire dinamicamente la sottostringa :)
Amresh Giri,

10

Per trovare occorrenze sovrapposte di una sottostringa in una stringa in Python 3, questo algoritmo farà:

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  

Io stesso ho controllato questo algoritmo e ha funzionato.


1
Piccolo consiglio: invece di dire "Funziona perché l'ho controllato", potresti includere un esempio su un servizio online come repl.it con alcuni dati di esempio.
Valentin,

1
grazie per il tuo commento Valentin! È la mia prima risposta qui. Mi migliorerò dalle mie prossime risposte.
Bharath Kumar R,

10

Puoi contare la frequenza in due modi:

  1. Utilizzando count()in str:

    a.count(b)

  2. Oppure puoi usare:

    len(a.split(b))-1

Dov'è ala stringa ed bè la sottostringa la cui frequenza deve essere calcolata.


7

L'attuale migliore risposta che coinvolge il metodo countnon conta davvero per le occorrenze sovrapposte e non si preoccupa anche delle sottostringhe vuote. Per esempio:

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

La prima risposta dovrebbe essere 2no1 , se consideriamo le stringhe che si sovrappongono. Per quanto riguarda la seconda risposta, è meglio se una sottostringa vuota restituisce 0 come risposta.

Il seguente codice si occupa di queste cose.

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

Ora quando lo eseguiamo:

>>>num_of_patterns('caatatab', 'ata') #overlapping
2
>>>num_of_patterns('caatatab', '') #empty string
0
>>>num_of_patterns('abcdabcva','ab') #normal
2

6

Scenario 1: occorrenza di una parola in una frase. ad es str1 = "This is an example and is easy". : . La ricorrenza della parola "è". lasciastr2 = "is"

count = str1.count(str2)

Scenario 2: occorrenza di pattern in una frase.

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

Grazie!


abbiamo davvero bisogno di questo controllo se (string [j] == sub_string [0]):? non è automaticamente coperto nelle successive condizioni if?
AnandViswanathan89,

AnandViswanathan89, Entrambi se sono richieste condizioni, if (string [j] == sub_string [0]) controlla la corrispondenza del carattere iniziale all'interno della stringa principale, che deve essere eseguita per tutti i caratteri della stringa principale e if (stringa [ j: j + len2] == sub_string) esegue l'occorrenza della sottostringa. Se è per la prima occorrenza, quindi per la seconda se la condizione sarebbe stata sufficiente.
Amith VV,

4

La domanda non è molto chiara, ma risponderò a quello che stai chiedendo, in superficie.

Una stringa S, che è lunga L caratteri e dove S [1] è il primo carattere della stringa e S [L] è l'ultimo carattere, ha le seguenti sottostringhe:

  • La stringa null ''. Ce n'è uno di questi.
  • Per ogni valore A da 1 a L, per ogni valore B da A a L, la stringa S [A] .. S [B] (incluso). Ci sono L + L-1 + L-2 + ... 1 di queste stringhe, per un totale di 0,5 * L * (L + 1).
  • Si noti che il secondo elemento include S [1] .. S [L], ovvero l'intera stringa originale S.

Quindi, ci sono 0,5 * L * (L + 1) + 1 sottostringhe all'interno di una stringa di lunghezza L. Renderizza quell'espressione in Python e hai il numero di sottostringhe presenti all'interno della stringa.


4

Un modo è usare re.subn. Ad esempio, per contare il numero di occorrenze 'hello'in qualsiasi mix di casi puoi fare:

import re
_, count = re.subn(r'hello', '', astring, flags=re.I)
print('Found', count, 'occurrences of "hello"')

Parola per me, grazie. @santosh, perché non accettare una risposta?
Mawg dice di ripristinare Monica il

2

Terrò la mia risposta accettata come il "modo semplice ed ovvio per farlo", tuttavia, ciò non copre gli eventi sovrapposti. Scoprirli ingenuamente, con il controllo multiplo delle sezioni - come in: sum ("GCAAAAAGH" [i:]. Inizia con ("AAA") per i nell'intervallo (len ("GCAAAAAGH")))

(che produce 3) - può essere fatto usando un trucco delle espressioni regolari, come si può vedere in Python regex trovare tutte le corrispondenze sovrapposte? - e può anche essere utile per giocare a golf in codice fine - Questo è il mio conteggio "fatto a mano" per le sovrapposizioni di schemi in una stringa che cerca di non essere estremamente ingenuo (almeno non crea nuovi oggetti stringa ad ogni interazione):

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

Occorrenze sovrapposte:

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

risultati:

my maaather lies over the oceaaan
6
4
2

2

Per il conteggio sovrapposto possiamo usare usare:

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

Per i casi non sovrapposti possiamo usare la funzione count ():

string.count(sub_string)

2

Che ne dici di un one-liner con una comprensione della lista? Tecnicamente i suoi 93 caratteri sono lunghi, risparmiami il purismo PEP-8. La risposta regex.findall è la più leggibile se è un pezzo di codice di alto livello. Se stai costruendo qualcosa di basso livello e non vuoi dipendenze, questo è piuttosto snello e cattivo. Sto dando la risposta sovrapposta. Ovviamente basta usare il conteggio come la risposta del punteggio più alto se non ci sono sovrapposizioni.

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

Se vuoi contare tutte le sottostringhe (comprese quelle sovrapposte), usa questo metodo.

import re
def count_substring(string, sub_string):
    regex = '(?='+sub_string+')'
    # print(regex)
    return len(re.findall(regex,string))

1

Se vuoi scoprire il conteggio della sottostringa all'interno di qualsiasi stringa; si prega di utilizzare sotto il codice. Il codice è facile da capire, ecco perché ho saltato i commenti. :)

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

Non sono sicuro che si tratti già di qualcosa, ma ho pensato a questo come una soluzione per una parola "usa e getta":

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

print count

Dove parola è la parola che stai cercando e il termine è il termine che stai cercando


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
Forse puoi approfondire come questa soluzione è diversa dall'altra, c'è un caso speciale che è in grado di risolvere?
mpaskov

2
Sebbene questo codice possa rispondere alla domanda, fornire un contesto aggiuntivo riguardo a come e / o perché risolve il problema migliorerebbe il valore a lungo termine della risposta.
Paperino

0
import re
d = [m.start() for m in re.finditer(seaching, string)] 
print (d)

Questo trova il numero di volte in cui la stringa secondaria è stata trovata nella stringa e visualizza l'indice.


import re d = [m.start () per m in re.finditer (st3, st2)] #finding il numero di volte che la stringa secondaria è stata trovata nella stringa e visualizza l'indice stampa (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

Rischiare un downvote perché altri 2+ hanno già fornito questa soluzione. Ne ho persino votato uno. Ma il mio è probabilmente il più facile da capire per i neofiti.

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

Per una stringa semplice con delimitazione dello spazio, l'uso di Dict sarebbe piuttosto veloce, vedere il codice come di seguito

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

È possibile utilizzare il startswithmetodo:

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

La logica sottostante funzionerà per tutte le stringhe e i caratteri speciali

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

Ecco la soluzione in Python 3 e maiuscole e minuscole:

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
Sebbene tutte le risposte siano apprezzate, solo le risposte in codice tendono a non spiegare molto bene l'argomento. Si prega di aggiungere un po 'di contesto.
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

Questo crea un elenco di tutte le occorrenze (anche sovrapposte) nella stringa e le conta

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

Esempio:

str1 ='abcabcd'
str2 = 'bc'

creerà questo elenco ma salverà solo i valori BOLD :

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

che restituirà:

len([bc, bc])

1
Ti preghiamo di considerare di aggiungere almeno qualche spiegazione, come se il motivo per cui questa risposta alla domanda
β.εηοιτ.βε

0

Ecco una soluzione che funziona sia per occorrenze non sovrapposte che sovrapposte. Per chiarire: una sottostringa sovrapposta è quella il cui ultimo carattere è identico al suo primo carattere.

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
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.