Cuenta el número de ocurrencias de una subcadena dada en una cadena

201

¿Cómo puedo contar la cantidad de veces que una subcadena determinada está presente dentro de una cadena en Python?

Por ejemplo:

>>> 'foo bar foo'.numberOfOccurrences('foo')
2
santosh
fuente
¿Qué quiere decir con "número de subcadena"? La posición de la subcadena? ¿Cuántas veces se produce la subcadena? ¿Algo más?
GreenMatt
2
¿Es esta una tarea? Si es así, agregue la etiqueta "tarea" a su pregunta. Además, su pregunta no es muy clara. Contestaré lo que pareces preguntar, pero sospecho que realmente quieres descubrir algo más.
Jim DeLaHunt
Después del comentario anterior, es posible que desee ver: python: cómo encontrar una subcadena en otra cadena o las recurrencias de indexación básica de una subcadena dentro de una cadena (python) . Como esto parece un duplicado probable de uno de esos, estoy votando para cerrar.
GreenMatt
@JimDeLaHunt Para los registros, hay un ejercicio sobre esto en cscircles.cemc.uwaterloo.ca/8-remix - vea Ejercicio de codificación: Conteo de subcadenas .
Nikos Alexandris

Respuestas:

335

string.count(substring), como en:

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

Actualizar:

Como se señaló en los comentarios, esta es la forma de hacerlo para casos no superpuestos . Si necesita contar las ocurrencias superpuestas, será mejor que verifique las respuestas en: "¿ Python regex encuentra todas las coincidencias superpuestas? ", O simplemente verifique mi otra respuesta a continuación.

jsbueno
fuente
14
¿Qué pasa con esto: "GCAAAAAG".count("AAA")que da 1, mientras que la respuesta correcta es 3?
dibujante
12
countobviamente es para coincidencias no superpuestas, que a menudo es lo que uno quiere hacer. stackoverflow.com/questions/5616822/… trata con coincidencias superpuestas, pero una expresión simple, aunque costosa, es:sum("GCAAAAAGH"[i:].startswith("AAA") for i in range(len("GCAAAAAGH")))
jsbueno
¿Es posible contar / buscar varias palabras a la vez? como string.count (substring1, substring2)
Sushant Kulkarni
@SushantKulkarni No. Aunque hay una forma lógica de hacer tal cosa: string.count(substring1) + string.count(substring2). Pero tenga en cuenta que este no es un método eficiente si hay muchas subcadenas porque contar cada subcadena requiere una iteración sobre la cadena principal.
Faheel
Hacer @SushantKulkarni ''.join([substring1, substring2]).count(pattern)es más eficiente que la solución sugerida anteriormente. Lo comprobé usando 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
fuente
44
Una explicación adicional mejoraría su respuesta.
ryanyuyu
19

Dependiendo de lo que realmente quiere decir, propongo las siguientes soluciones:

  1. Te refieres a una lista de subcadenas separadas por espacios y quieres saber cuál es el número de posición de la subcadena entre todas las subcadenas:

    s = 'sub1 sub2 sub3'
    s.split().index('sub2')
    >>> 1
  2. Te refieres a la posición char de la subcadena en la cadena:

    s.find('sub2')
    >>> 5
  3. Te refieres a los recuentos (no superpuestos) de apariencia de una su-bstring:

    s.count('sub2')
    >>> 1
    s.count('sub')
    >>> 3
Don Question
fuente
Trate de encontrar 'sub' o 'su'
obohovyk
Supongo que te refieres s.find("su")y te preguntas por qué lo haces 0. Bueno, este es el primer índice de la subcadena "su"en s. Pruebe "ub"y obtendrá 1, intente, por ejemplo, "z"y obtendrá -1como en ninguna subcadena encontrada.
Don Question
Quiero decir que siempre encuentras solo el primer índice, pero no todos los índices, @ arun-kumar-khattri dio la respuesta correcta
obohovyk
Me alivia que @ arun-kumar-khattri haya dado la respuesta "correcta" que estaba buscando. Tal vez deberías echar un vistazo adicional a los comentarios de jsbueno, a veces responden preguntas que aún no has hecho.
Don Question
Como para el tercer enfoque. Por cierto, creo que debería mencionar que funciona para casos no superpuestos.
Zeinab Abbasimazar
12

La mejor manera de encontrar subcadenas superpuestas en una cadena dada es usar la expresión regular de python, encontrará todas las coincidencias superpuestas usando la biblioteca de expresiones regulares. Aquí es cómo hacerlo a la izquierda es la subcadena y en la derecha proporcionará la cadena para que coincida

print len(re.findall('(?=aa)','caaaab'))
3
Deepak Yadav
fuente
2
tal vez podría agregar len (re.findall (f '(? = {sub_string})', 'caaaab')) para insertar la subcadena dinámicamente :)
Amresh Giri
10

Para encontrar ocurrencias superpuestas de una subcadena en una cadena en Python 3, este algoritmo hará:

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  

Yo mismo revisé este algoritmo y funcionó.

Bharath Kumar R
fuente
1
Pequeño consejo: en lugar de decir "Funciona porque lo verifiqué", podría incluir un ejemplo en un servicio en línea como repl.it con algunos datos de muestra.
Valentin
1
gracias por tu comentario Valentin! Es mi primera respuesta aquí. Me mejoraré a partir de mis próximas respuestas.
Bharath Kumar R
10

Puede contar la frecuencia de dos maneras:

  1. Usando el count()en str:

    a.count(b)

  2. O puedes usar:

    len(a.split(b))-1

¿Dónde aestá la cadena y bla subcadena cuya frecuencia se va a calcular?

Anuj Gupta
fuente
7

La mejor respuesta actual que involucra el método countrealmente no cuenta para las ocurrencias superpuestas y tampoco le importan las subcadenas vacías. Por ejemplo:

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

La primera respuesta debería ser 2no1 , si tenemos en cuenta las subcadenas que se solapan. En cuanto a la segunda respuesta, es mejor si una subcadena vacía devuelve 0 como respuesta.

El siguiente código se ocupa de estas cosas.

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

Ahora cuando lo ejecutamos:

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

Escenario 1: aparición de una palabra en una oración. por ejemplo: str1 = "This is an example and is easy". La aparición de la palabra "es". dejastr2 = "is"

count = str1.count(str2)

Escenario 2: aparición de un patrón en una oración.

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

¡Gracias!

Amith VV
fuente
¿realmente necesitamos esta verificación if (string [j] == sub_string [0]):? ¿no se cubre automáticamente en la condición posterior si?
AnandViswanathan89
AnandViswanathan89, tanto si se requieren condiciones, si (string [j] == sub_string [0]) verifica la coincidencia de caracteres inicial dentro de la cadena principal, que debe realizarse para todos los caracteres de la cadena principal y if (string [ j: j + len2] == sub_string) realiza la aparición de la subcadena. Si es por la primera vez, la segunda si la condición hubiera sido suficiente.
Amith VV
4

La pregunta no es muy clara, pero responderé lo que eres, en la superficie, preguntando.

Una cadena S, que tiene una longitud de L caracteres y donde S [1] es el primer carácter de la cadena y S [L] es el último carácter, tiene las siguientes subcadenas:

  • La cadena nula ''. Hay uno de estos.
  • Para cada valor A de 1 a L, para cada valor B de A a L, la cadena S [A] .. S [B] (inclusive). Hay L + L-1 + L-2 + ... 1 de estas cadenas, para un total de 0.5 * L * (L + 1).
  • Tenga en cuenta que el segundo elemento incluye S [1] .. S [L], es decir, toda la cadena original S.

Entonces, hay 0.5 * L * (L + 1) + 1 subcadenas dentro de una cadena de longitud L. Renderice esa expresión en Python, y tiene el número de subcadenas presentes dentro de la cadena.

Jim DeLaHunt
fuente
4

Una forma es usar re.subn. Por ejemplo, para contar el número de ocurrencias de 'hello'cualquier combinación de casos que puede hacer:

import re
_, count = re.subn(r'hello', '', astring, flags=re.I)
print('Found', count, 'occurrences of "hello"')
Eugene Yarmash
fuente
Palabra para mí, gracias. @santosh, ¿por qué no aceptar una respuesta?
Mawg dice que reinstale a Mónica el
2

Mantendré mi respuesta aceptada como la "forma simple y obvia de hacerlo"; sin embargo, eso no cubre las superposiciones. Averiguarlos se puede hacer ingenuamente, con múltiples comprobaciones de los cortes, como en: sum ("GCAAAAAGH" [i:]. Comienza con ("AAA") para i en rango (len ("GCAAAAAGH")))

(que produce 3): ¿se puede hacer mediante el uso engañoso de expresiones regulares, como se puede ver en Python regex encontrar todas las coincidencias superpuestas? - y también puede hacer golf de código fino - Este es mi recuento "hecho a mano" para la superposición de ocurrencias de patrones en una cadena que intenta no ser extremadamente ingenua (al menos no crea nuevos objetos de cadena en cada interacción):

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
fuente
2

Ocurrencias superpuestas:

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

Resultados:

my maaather lies over the oceaaan
6
4
2
fyngyrz
fuente
2

Para el recuento superpuesto podemos usar use:

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

Para casos no superpuestos podemos usar la función count ():

string.count(sub_string)
Dhiraj Dwivedi
fuente
2

¿Qué tal un one-liner con una lista de comprensión? Técnicamente sus 93 caracteres de largo, me ahorran el purismo PEP-8. La respuesta regex.findall es la más legible si se trata de un código de alto nivel. Si está creando algo de bajo nivel y no quiere dependencias, este es bastante delgado y malo. Estoy dando la respuesta superpuesta. Obviamente, use el conteo como la respuesta de mayor puntaje si no hay superposición.

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
fuente
2

Si desea contar todas las subcadenas (incluidas las superpuestas), utilice este método.

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

Si desea averiguar el recuento de subcadenas dentro de cualquier cadena; por favor use el siguiente código. El código es fácil de entender, por eso me salté los comentarios. :)

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
fuente
0

No estoy seguro de si esto ya es algo visto, pero pensé en esto como una solución para una palabra que es 'desechable':

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

print count

Donde palabra es la palabra que está buscando y término es el término que está buscando

Alan Vinton
fuente
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
fuente
2
Quizás pueda explicar cómo esta solución es diferente de la otra, ¿hay algún caso especial que pueda resolver?
mpaskov
2
Si bien este código puede responder la pregunta, proporcionar un contexto adicional con respecto a cómo y / o por qué resuelve el problema mejoraría el valor a largo plazo de la respuesta.
Donald Duck
0
import re
d = [m.start() for m in re.finditer(seaching, string)] 
print (d)

Esto encuentra el número de veces que la subcadena se encuentra en la cadena y muestra el índice.

Bhaskar Reddi K
fuente
import re d = [m.start () para m en re.finditer (st3, st2)] #encontrando el número de veces que se encuentra la subcadena en la cadena y muestra la impresión de índice (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
fuente
0

Arriesgar un voto negativo porque más de 2 personas ya han proporcionado esta solución. Incluso voté a uno de ellos. Pero el mío es probablemente el más fácil de entender para los novatos.

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
fuente
0

Para una cadena simple con delimitación de espacio, usar Dict sería bastante rápido, consulte el código a continuación

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
fuente
0

Podrías usar el startswithmétodo:

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
fuente
0

La lógica a continuación funcionará para todas las cadenas y caracteres especiales

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
fuente
0

Aquí está la solución en Python 3 y no distingue entre mayúsculas y minúsculas:

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
fuente
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
fuente
2
Si bien todas las respuestas son apreciadas, las respuestas de solo código tienden a no explicar muy bien el tema. Por favor agregue algo de contexto.
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
fuente
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
fuente
0

Esto hace una lista de todas las ocurrencias (también superpuestas) en la cadena y las cuenta

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

Ejemplo:

str1 ='abcabcd'
str2 = 'bc'

creará esta lista pero solo guardará los valores BOLD :

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

eso devolverá:

len([bc, bc])
Elad L.
fuente
1
Considere agregar al menos alguna explicación como si esto respondiera la pregunta
β.εηοιτ.βε
0

Aquí hay una solución que funciona tanto para casos no superpuestos como superpuestos. Para aclarar: una subcadena superpuesta es aquella cuyo último carácter es idéntico a su primer carácter.

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
fuente