Encuentre el número de ocurrencias de una subcadena en una cadena

6 minutos de lectura

¿Por qué el siguiente algoritmo no se detiene para mí?

En el código de abajo, str es la cadena en la que estoy buscando, y findStr es la cadena de ocurrencias de las que estoy tratando de encontrar.

String str = "helloslkhellodjladfjhello";
String findStr = "hello";
int lastIndex = 0;
int count = 0;
    
while (lastIndex != -1) {
    lastIndex = str.indexOf(findStr,lastIndex);
    
    if( lastIndex != -1)
        count++;
           
    lastIndex += findStr.length();
}

System.out.println(count);

  • Hicimos uno muy bueno en Udacity: usamos newSTR = str.replace(findStr, “”); y devolvió count = ((str.length() – newSTR.length())/findStr.length());

    – SolarLunix

    14/09/2015 a las 17:46

  • Pregunta similar para personajes: stackoverflow.com/q/275944/873282

    – koppor

    16/04/2017 a las 19:42

  • ¿No desea tener en cuenta también el caso en que el prefijo de la cadena de búsqueda es su sufijo? En ese caso, no creo que ninguna de las respuestas sugeridas funcione. aquí es un ejemplo En ese caso, necesitaría un algoritmo más elaborado, como el Knuth Morris Pratt (KMP), que está codificado en el libro CLRS.

    – Sid

    25 de julio de 2017 a las 15:42


  • no se detiene para usted, porque después de alcanzar su condición de ‘detención’ (lastIndex == -1) lo reinicia incrementando el valor de lastIndex (lastIndex += findStr.length();)

    – Legna

    01/08/2017 a las 22:30

  • @Sid si quisiera ese comportamiento, simplemente podría incrementar lastIndex en solo 1 cada vez en lugar de findStr.length. En mi caso, por ejemplo, solo necesito saber si un personaje coincide o no, no me importa contar varias superposiciones. así que solo depende de cada caso de uso individual

    – Adam Burley

    30 de enero de 2021 a las 2:44

Avatar de usuario de A_M
SOY

¿Qué hay de usar StringUtils.countMatches de Apache Commons Lang?

String str = "helloslkhellodjladfjhello";
String findStr = "hello";

System.out.println(StringUtils.countMatches(str, findStr));

Eso da como resultado:

3

  • No importa cuán correcta sea esta sugerencia, no puede aceptarse como la solución ya que no responde la pregunta de OP

    – kommradHomer

    12 de julio de 2014 a las 11:36

  • ¿Está obsoleto o algo así? Mi IDE no reconoce

    – Vamsi Pavan Mahesh

    18/07/2014 a las 16:30

  • @VamsiPavanMahesh StringUtils es una biblioteca de Apache Commons. Chequea aquí : commons.apache.org/proper/commons-lang/javadocs/api-2.6/org/…

    – Anup

    15/09/2015 a las 11:33

  • Esta respuesta es una copia de la respuesta de Peter Lawrey un día antes (ver más abajo).

    – Zona

    14/03/2016 a las 14:36

  • StringUtils no tiene countMatches método.

    – camisa a cuadros

    10 de mayo de 2018 a las 9:19

Avatar de usuario de Olivier
olivier

Tu lastIndex += findStr.length(); se colocó fuera de los corchetes, lo que provocó un bucle infinito (cuando no se encontró ninguna ocurrencia, lastIndex siempre findStr.length()).

Aquí está la versión fija:

String str = "helloslkhellodjladfjhello";
String findStr = "hello";
int lastIndex = 0;
int count = 0;

while (lastIndex != -1) {

    lastIndex = str.indexOf(findStr, lastIndex);

    if (lastIndex != -1) {
        count++;
        lastIndex += findStr.length();
    }
}
System.out.println(count);

  • Esto fallará para la cadena “aaa” y la subcadena “aa”. Devolverá 1 mientras la cuenta es dos. Los índices de las ocurrencias son [0,1]

    – Niko

    14/10/2021 a las 21:31

  • @Niko El resultado correcto depende de si se permiten o no coincidencias superpuestas.

    – Sin paliativos

    14 de mayo a las 16:36

Avatar de usuario de Peter Lawrey
pedro laurey

Una versión más corta. 😉

String str = "helloslkhellodjladfjhello";
String findStr = "hello";
System.out.println(str.split(findStr, -1).length-1);

  • return haystack.split(Pattern.quote(needle), -1).length - 1; si por ejemplo needle=":)"

    – Sr_y_Sra_D

    16 de diciembre de 2012 a las 16:01

  • @lOranger Sin el ,-1 arrojará coincidencias finales.

    – Peter Lawrey

    28 de diciembre de 2012 a las 12:02

  • ¡Ay, gracias, es bueno saberlo! Esto me enseñará a leer las líneas pequeñas en el javadoc…

    – Laurent Grégoire

    28 de diciembre de 2012 a las 12:05

  • ¡Bonito! Pero solo incluye coincidencias que no se superponen, ¿no? Por ejemplo, hacer coincidir “aa” en “aaa” devolverá 1, no 2. Por supuesto, la inclusión de coincidencias superpuestas o no superpuestas es válida y depende de los requisitos del usuario (tal vez una bandera para indicar superposiciones de recuento, sí/no).

    -Cornel Masson

    26 de abril de 2013 a las 9:24


  • -1 .. intente ejecutar esto en “aaaa” y “aa”.. la respuesta correcta es 3, no 2.

    – Kalyanaraman Santhanam

    15 de septiembre de 2014 a las 6:06

avatar de usuario de codebreach
incumplimiento de código

La última línea estaba creando un problema. lastIndex nunca estaría en -1, por lo que habría un bucle infinito. Esto se puede solucionar moviendo la última línea de código al bloque if.

String str = "helloslkhellodjladfjhello";
String findStr = "hello";
int lastIndex = 0;
int count = 0;

while(lastIndex != -1){

    lastIndex = str.indexOf(findStr,lastIndex);

    if(lastIndex != -1){
        count ++;
        lastIndex += findStr.length();
    }
}
System.out.println(count);

Avatar de usuario de Jean
Vaquero

¿Realmente tienes que encargarte tú mismo del emparejamiento? Especialmente si todo lo que necesita es el número de ocurrencias, las expresiones regulares son más ordenadas:

String str = "helloslkhellodjladfjhello";
Pattern p = Pattern.compile("hello");
Matcher m = p.matcher(str);
int count = 0;
while (m.find()){
    count +=1;
}
System.out.println(count);     

  • Esto NO encuentra caracteres especiales, encontrará 0 recuentos para las cadenas a continuación: String str = "hel+loslkhel+lodjladfjhel+lo"; Pattern p = Pattern.compile("hel+lo");

    – ben

    2 de febrero de 2014 a las 4:09


  • sí lo hará si expresa su expresión regular correctamente. prueba con Pattern.compile("hel\\+lo"); el + El signo tiene un significado especial en una expresión regular y debe escaparse.

    – Juan

    2 de febrero de 2014 a las 9:42

  • Si lo que está buscando es tomar una cadena arbitraria y usarla como una coincidencia exacta con todos los caracteres especiales de expresión regular ignorados, Pattern.quote(str) ¡es tu amigo!

    –Mike Furtak

    10 de enero de 2015 a las 18:11


  • esto no funciona para “aaa” cuando str = “aaaaaa”. Hay 4 respuestas pero la tuya da 2

    – Puján

    29 de octubre de 2016 a las 12:02

  • Esta solución no funciona para este caso: str = “Esta es una cadena de prueba \\n\\r”, subStr = “\\r”, muestra 0 ocurrencias.

    – Maksim Ovsianikov

    1 de diciembre de 2017 a las 23:21

Estoy muy sorprendido de que nadie haya mencionado este trazador de líneas. Es simple, conciso y funciona un poco mejor que str.split(target, -1).length-1

public static int count(String str, String target) {
    return (str.length() - str.replace(target, "").length()) / target.length();
}

  • Esto NO encuentra caracteres especiales, encontrará 0 recuentos para las cadenas a continuación: String str = "hel+loslkhel+lodjladfjhel+lo"; Pattern p = Pattern.compile("hel+lo");

    – ben

    2 de febrero de 2014 a las 4:09


  • sí lo hará si expresa su expresión regular correctamente. prueba con Pattern.compile("hel\\+lo"); el + El signo tiene un significado especial en una expresión regular y debe escaparse.

    – Juan

    2 de febrero de 2014 a las 9:42

  • Si lo que está buscando es tomar una cadena arbitraria y usarla como una coincidencia exacta con todos los caracteres especiales de expresión regular ignorados, Pattern.quote(str) ¡es tu amigo!

    –Mike Furtak

    10 de enero de 2015 a las 18:11


  • esto no funciona para “aaa” cuando str = “aaaaaa”. Hay 4 respuestas pero la tuya da 2

    – Puján

    29 de octubre de 2016 a las 12:02

  • Esta solución no funciona para este caso: str = “Esta es una cadena de prueba \\n\\r”, subStr = “\\r”, muestra 0 ocurrencias.

    – Maksim Ovsianikov

    1 de diciembre de 2017 a las 23:21

Aquí está, envuelto en un método agradable y reutilizable:

public static int count(String text, String find) {
        int index = 0, count = 0, length = find.length();
        while( (index = text.indexOf(find, index)) != -1 ) {                
                index += length; count++;
        }
        return count;
}

¿Ha sido útil esta solución?