Compter le nombre d'occurrences d'une sous-chaîne donnée dans une chaîne

201

Comment puis-je compter le nombre de fois qu'une sous-chaîne donnée est présente dans une chaîne en Python?

Par exemple:

>>> 'foo bar foo'.numberOfOccurrences('foo')
2
Santosh
la source
Qu'entendez-vous par «nombre de sous-chaînes»? La position de la sous-chaîne? Combien de fois la sous-chaîne se produit-elle? Autre chose?
GreenMatt
2
S'agit-il d'un devoir? Si oui, veuillez ajouter la balise "devoirs" à votre question. De plus, votre question n'est pas très claire. Je répondrai à ce que vous semblez demander, mais je soupçonne que vous voulez vraiment découvrir autre chose.
Jim DeLaHunt
Après le commentaire précédent, vous voudrez peut-être voir: python: comment trouver une sous-chaîne dans une autre chaîne ou les récurrences d'indexation de base d'une sous-chaîne dans une chaîne (python) . Comme cela semble être un double probable de l'un d'entre eux, je vote pour clore.
GreenMatt
@JimDeLaHunt Pour les enregistrements, il y a un exercice à ce sujet dans cscircles.cemc.uwaterloo.ca/8-remix - voir Exercice de codage: comptage des sous-chaînes .
Nikos Alexandris
2
Duplication possible des récurrences d'indexation
Valentin

Réponses:

335

string.count(substring), comme dans:

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

Mettre à jour:

Comme indiqué dans les commentaires, c'est la façon de procéder pour les occurrences qui ne se chevauchent pas . Si vous avez besoin de compter les occurrences qui se chevauchent, vous feriez mieux de vérifier les réponses à: " Python regex trouver toutes les correspondances qui se chevauchent? ", Ou tout simplement vérifier mon autre réponse ci-dessous.

jsbueno
la source
14
Qu'en est-il de cela: ce "GCAAAAAG".count("AAA")qui donne 1, tandis que la bonne réponse est 3?
dessinateur
12
countest évidemment pour les correspondances qui ne se chevauchent pas - ce qui est le plus souvent ce que l'on veut faire. stackoverflow.com/questions/5616822/… traite des correspondances qui se chevauchent - mais une expression simple, mais coûteuse, est:sum("GCAAAAAGH"[i:].startswith("AAA") for i in range(len("GCAAAAAGH")))
jsbueno
Est-il possible de compter / rechercher plusieurs mots à la fois? comme string.count (substring1, substring2)
Sushant Kulkarni
Non @SushantKulkarni Bien qu'il y ait une façon logique de faire une telle chose: string.count(substring1) + string.count(substring2). Mais gardez à l'esprit que ce n'est pas une méthode efficace s'il y a beaucoup de sous-chaînes car le comptage de chaque sous-chaîne nécessite une itération sur la chaîne principale.
Faheel
@SushantKulkarni ''.join([substring1, substring2]).count(pattern)est plus efficace que la solution suggérée ci-dessus. J'ai vérifié en utilisant timeit.
Enric Calabuig
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
Arun Kumar Khattri
la source
4
Des explications supplémentaires amélioreraient votre réponse.
ryanyuyu
19

Selon ce que vous voulez vraiment dire, je vous propose les solutions suivantes:

  1. Vous voulez dire une liste de sous-chaînes séparées par des espaces et vous voulez savoir quel est le numéro de position de la sous-chaîne parmi toutes les sous-chaînes:

    s = 'sub1 sub2 sub3'
    s.split().index('sub2')
    >>> 1
  2. Vous voulez dire la position char de la sous-chaîne dans la chaîne:

    s.find('sub2')
    >>> 5
  3. Vous voulez dire que les (non-chevauchement) compte d'apparition d'un su-bstring:

    s.count('sub2')
    >>> 1
    s.count('sub')
    >>> 3
Don Question
la source
Essayez de trouver «sub» ou «su»
obohovyk
Je suppose que vous voulez dire s.find("su")et vous demandez pourquoi vous obtenez 0? Eh bien , c'est le premier indice de la sous-chaîne "su"dans s. Essayez "ub"et vous obtiendrez 1, essayez par exemple "z"et vous obtiendrez -1comme dans aucune sous-chaîne trouvée.
Don Question
Je veux dire que vous ne trouvez toujours que le premier index, mais pas tous les index, @ arun-kumar-khattri a donné la bonne réponse
obohovyk
Je suis soulagé que @ arun-kumar-khattri ait donné la "bonne" réponse que vous cherchiez. Vous devriez peut-être jeter un coup d'œil supplémentaire aux commentaires de jsbueno, parfois ils répondent à des questions que vous n'avez pas encore posées.
Don Question
Comme pour la troisième approche. BTW, je pense que vous devriez mentionner que cela fonctionne pour les cas qui ne se chevauchent pas.
Zeinab Abbasimazar
12

La meilleure façon de trouver une sous-chaîne qui se chevauchent dans une chaîne donnée est d'utiliser l'expression régulière python, elle trouvera toutes les correspondances qui se chevauchent en utilisant la bibliothèque d'expressions régulières. Voici comment le faire à gauche est la sous-chaîne et à droite vous fournirez la chaîne à faire correspondre

print len(re.findall('(?=aa)','caaaab'))
3
Deepak Yadav
la source
2
vous pouvez peut-être ajouter len (re.findall (f '(? = {sub_string})' ',' caaaab ')) pour insérer la sous-chaîne de façon dynamique :)
Amresh Giri
10

Pour trouver les occurrences qui se chevauchent d'une sous-chaîne dans une chaîne en Python 3, cet algorithme fera:

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  

J'ai moi-même vérifié cet algorithme et cela a fonctionné.

Bharath Kumar R
la source
1
Petit conseil: au lieu de dire "Ça marche parce que je l'ai vérifié", vous pouvez inclure un exemple sur un service en ligne comme repl.it avec quelques exemples de données.
Valentin
1
merci pour ton commentaire Valentin! C'est ma première réponse ici. Je vais m'améliorer à partir de mes prochaines réponses.
Bharath Kumar R
10

Vous pouvez compter la fréquence de deux manières:

  1. Utilisation de count()in str:

    a.count(b)

  2. Ou, vous pouvez utiliser:

    len(a.split(b))-1

aest la chaîne et bla sous-chaîne dont la fréquence doit être calculée.

Anuj Gupta
la source
7

La meilleure méthode de réponse actuelle countne compte pas vraiment pour les occurrences qui se chevauchent et ne se soucie pas non plus des sous-chaînes vides. Par exemple:

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

La première réponse ne devrait 2pas être 1, si l'on considère les sous-chaînes qui se chevauchent. Quant à la deuxième réponse, il est préférable qu'une sous-chaîne vide renvoie 0 comme réponse.

Le code suivant s'occupe de ces choses.

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

Maintenant, quand nous l'exécutons:

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

Scénario 1: occurrence d'un mot dans une phrase. par exemple: str1 = "This is an example and is easy". L'occurrence du mot "est". laissestr2 = "is"

count = str1.count(str2)

Scénario 2: occurrence du motif dans une phrase.

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

Merci!

Amith VV
la source
avons-nous vraiment besoin de cette vérification si (string [j] == sub_string [0]):? n'est-il pas automatiquement couvert dans la condition if suivante?
AnandViswanathan89
AnandViswanathan89, Les deux si des conditions sont requises, si (chaîne [j] == chaîne_sous [0]) vérifie la correspondance de caractères initiale dans la chaîne principale, qui doit être effectuée pour tous les caractères de la chaîne principale et si (chaîne [ j: j + len2] == sub_string) effectue l'occurrence de la sous-chaîne. S'il s'agit de la première occurrence, la seconde si la condition aurait suffi.
Amith VV
4

La question n'est pas très claire, mais je vais répondre à ce que vous demandez, à première vue.

Une chaîne S, longue de L caractères, et où S [1] est le premier caractère de la chaîne et S [L] est le dernier caractère, a les sous-chaînes suivantes:

  • La chaîne nulle ''. Il y en a un.
  • Pour chaque valeur A de 1 à L, pour chaque valeur B de A à L, la chaîne S [A] .. S [B] (inclus). Il y a L + L-1 + L-2 + ... 1 de ces chaînes, pour un total de 0,5 * L * (L + 1).
  • Notez que le deuxième élément comprend S [1] .. S [L], c'est-à-dire la chaîne originale entière S.

Donc, il y a 0,5 * L * (L + 1) + 1 sous-chaînes dans une chaîne de longueur L. Rendez cette expression en Python, et vous avez le nombre de sous-chaînes présentes dans la chaîne.

Jim DeLaHunt
la source
4

Une façon est d'utiliser re.subn. Par exemple, pour compter le nombre d'occurrences de 'hello'dans n'importe quelle combinaison de cas, vous pouvez faire:

import re
_, count = re.subn(r'hello', '', astring, flags=re.I)
print('Found', count, 'occurrences of "hello"')
Eugene Yarmash
la source
Un mot pour moi, merci. @santosh, pourquoi ne pas accepter une réponse?
Mawg dit réintégrer Monica
2

Je garderai ma réponse acceptée comme étant "la manière simple et évidente de le faire" - mais cela ne couvre pas les événements qui se chevauchent. Les découvrir peut être fait naïvement, avec plusieurs vérifications des tranches - comme dans: sum ("GCAAAAAGH" [i:]. Commence par ("AAA") pour i dans la plage (len ("GCAAAAAGH")))

(ce qui donne 3) - cela peut être fait en utilisant des expressions régulières, comme on peut le voir sur regex Python trouver toutes les correspondances qui se chevauchent? - et cela peut aussi faire du golf à code fin - C'est mon compte "fait à la main" pour les superpositions de motifs dans une chaîne qui essaie de ne pas être extrêmement naïf (au moins, il ne crée pas de nouveaux objets de chaîne à chaque interaction):

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
la source
2

Occurrences qui se chevauchent:

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

Résultats:

my maaather lies over the oceaaan
6
4
2
fyngyrz
la source
2

Pour le nombre de chevauchements, nous pouvons utiliser:

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

Pour les cas sans chevauchement, nous pouvons utiliser la fonction count ():

string.count(sub_string)
Dhiraj Dwivedi
la source
2

Que diriez-vous d'un one-liner avec une compréhension de la liste? Techniquement ses 93 caractères de long, m'épargnent le purisme du PEP-8. La réponse regex.findall est la plus lisible si c'est un morceau de code de haut niveau. Si vous construisez quelque chose de bas niveau et ne voulez pas de dépendances, celui-ci est plutôt maigre et méchant. Je donne la réponse qui se chevauchent. Évidemment, utilisez simplement count comme la réponse la plus élevée s'il n'y a pas de chevauchement.

def count_substring(string, sub_string):
    return len([i for i in range(len(string)) if string[i:i+len(sub_string)] == sub_string])
Ryan Dines
la source
2

Si vous souhaitez compter toute la sous-chaîne (y compris les chevauchements), utilisez cette méthode.

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

Si vous souhaitez connaître le nombre de sous-chaînes dans une chaîne; veuillez utiliser le code ci-dessous. Le code est facile à comprendre, c'est pourquoi j'ai sauté les commentaires. :)

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
la source
0

Je ne sais pas si c'est déjà quelque chose à regarder, mais j'ai pensé à cela comme une solution pour un mot qui est «jetable»:

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

print count

mot est le mot que vous recherchez et terme est le terme que vous recherchez

Alan Vinton
la source
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)
kamran shaik
la source
2
Peut-être pouvez-vous expliquer en quoi cette solution est différente de l'autre, y a-t-il un cas particulier qu'elle est capable de résoudre?
mpaskov
2
Bien que ce code puisse répondre à la question, fournir un contexte supplémentaire concernant la manière et / ou la raison pour laquelle il résout le problème améliorerait la valeur à long terme de la réponse.
Donald Duck
0
import re
d = [m.start() for m in re.finditer(seaching, string)] 
print (d)

Cela trouve le nombre de fois que la sous-chaîne a été trouvée dans la chaîne et affiche l'index.

Bhaskar Reddi K
la source
import re d = [m.start () for m in re.finditer (st3, st2)] #finding the number of times sub string found in the string and display index 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)
Vinay Kumar Kuresi
la source
0

Risquer un downvote car 2+ autres ont déjà fourni cette solution. J'ai même voté pour l'un d'entre eux. Mais le mien est probablement le plus facile à comprendre pour les débutants.

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
la source
0

Pour une chaîne simple avec délimitation d'espace, l'utilisation de Dict serait assez rapide, veuillez consulter le code ci-dessous

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')
Amit Gowda
la source
0

Vous pouvez utiliser la startswithméthode:

def count_substring(string, sub_string):
    x = 0
    for i in range(len(string)):
        if string[i:].startswith(sub_string):
            x += 1
    return x
Trevor Maseleme
la source
0

La logique ci-dessous fonctionnera pour toutes les chaînes et caractères spéciaux

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
la source
0

Voici la solution en Python 3 et insensible à la casse:

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
la source
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
la source
2
Bien que toutes les réponses soient appréciées, seules les réponses codées tendent à ne pas expliquer très bien le sujet. Veuillez ajouter du contexte.
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)
pawan kumar
la source
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))
pawan kumar
la source
0

Cela fait une liste de toutes les occurrences (qui se chevauchent également) dans la chaîne et les compte

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

Exemple:

str1 ='abcabcd'
str2 = 'bc'

créera cette liste mais n'enregistrera que les valeurs BOLD :

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

qui reviendra:

len([bc, bc])
Elad L.
la source
1
Veuillez envisager d'ajouter au moins quelques explications comme si cela répondait à la question
β.εηοιτ.βε
0

Voici une solution qui fonctionne à la fois pour les occurrences qui ne se chevauchent pas et qui se chevauchent. Pour clarifier: une sous-chaîne qui se chevauche est une sous-chaîne dont le dernier caractère est identique à son premier caractère.

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
la source