JavaScript: cómo contar el número de ocurrencias de subcadenas en una cadena

En este tutorial, aprenda a contar la cantidad de subcadenas/cadenas dentro de otra cadena usando el método split() y expresiones regulares (regex), con y sin coincidencia estricta y distinción entre mayúsculas y minúsculas.

Introducción

Cuando trabaje con cadenas o grandes cantidades de texto, probablemente encontrará situaciones en las que necesite contar cuántas veces se produjo una subcadena específica dentro de otra cadena.

En este artículo, veremos cómo usar JavaScript para contar el número de ocurrencias de subcadenas en una cadena. Veremos los diversos enfoques y métodos para obtener ese número.

Pero antes de comenzar, primero definamos qué es una subcadena.

¿Qué es una subcadena?

Una subcadena es una secuencia claramente definida de caracteres consecutivos en una cadena. Por ejemplo, si tenemos la cadena "Mi nombre es John Doe", entonces "nombre es" es una subcadena, pero "es nombre" no lo es porque ya no es una secuencia consecutiva (hemos cambiado el orden de las palabras). Las palabras individuales como "is" y "name" son siempre subcadenas.

{.icon aria-hidden=“true”}

Nota: "y name is Jo" es una subcadena válida de "My name is John Doe" también. En otras palabras, las subcadenas no siempre son palabras completas, pueden ser mucho menos legibles.

Hay muchas formas de lograr esto en JavaScript, pero dos métodos principales son el método split() y las expresiones regulares.

Cuente el número de subcadenas en una cadena con el método split()

split() es un método de JavaScript para dividir cadenas en una matriz de subcadenas mientras se conserva la cadena original. Este método acepta un separador y separa una cadena en función de él. Si no se proporciona ningún separador, split() devuelve una matriz con un solo elemento: la cadena original.

{.icon aria-hidden=“true”}

Nota: Probablemente el ejemplo más obvio del separador es el espacio en blanco. Cuando lo proporciona como un separador para el método split(), la cadena original se dividirá cada vez que se produzca un espacio en blanco. Por lo tanto, el método split() devolverá una matriz de palabras individuales de la cadena original.

En este artículo, usaremos un truco útil para obtener el número de ocurrencias de una subcadena en una cadena. Estableceremos la subcadena para que sea el separador en el método split(). De esa manera, podemos extraer el número de ocurrencias de la subcadena de la matriz que devolvió el método split():

1
2
3
4
5
let myString = "John Doe has 5 oranges while Jane Doe has only 2 oranges, Jane gave Mike 1 of her orange so she is now left with only 1 Orange.";
let mySubString = "orange";

let count = myString.split(mySubString).length - 1;
console.log(count); // 3

El código anterior devolvió 3, pero myString tiene solo una instancia de la cadena "orange". Inspeccionemos lo que sucedió examinando la matriz creada después de dividir la cadena original con "naranja" como separador:

1
console.log(myString.split(mySubString));

Esto nos dará:

1
['John Doe has 5 ', 's which Jane Doe has only 2 ', 's, Jane gave Mike 1 of her ', ' so she is now left with only 1 Orange.']

Esencialmente, el método split() eliminó todas las apariciones de la cadena "orange" de la cadena original y la cortó en los lugares donde se eliminó la subcadena.

{.icon aria-hidden=“true”}

Nota: Observe cómo se aplica a la cadena "oranges" - "orange" es su subcadena, por lo tanto, split() elimina "orange " y nos deja solo con "s".

Como hemos encontrado tres apariciones de la cadena "naranja", la cadena original se dividió en tres lugares; por lo tanto, hemos producido cuatro subcadenas. Es por eso que necesitamos restar 1 de la longitud de la matriz cuando calculamos el número de ocurrencias de la subcadena.

Eso está bien, pero hay un naranja más en la cadena original: la última palabra es "Naranja". ¿Por qué no lo hemos contado en el ejemplo anterior? Eso es porque el método split() es sensible a mayúsculas y minúsculas, por lo tanto considera "orange" y "Orange" como elementos diferentes.

Si necesita hacer que su código no distinga entre mayúsculas y minúsculas, una buena solución sería convertir primero la cadena completa y la subcadena a un caso de texto particular antes de verificar si hay ocurrencias:

1
2
3
4
5
6
7
8
let myString = "John Doe has 5 oranges while Jane Doe has only 2 oranges, Jane gave Mike 1 of her orange so she is now left with only 1 Orange.";
let mySubString = "ORANGE";

let myStringLC = myString.toLowerCase();
let mySubStringLC = mySubString.toLowerCase();

let count = myStringLC.split(mySubStringLC).length - 1;
console.log(); // 4

Además, lo último que podríamos hacer es hacer que nuestro código sea reutilizable envolviéndolo con una función:

1
2
3
4
5
6
7
8
const countOccurence = (string, word) => {
    let stringLC = string.toLowerCase();
    let wordLC = word.toLowerCase();
    
    let count = stringLC.split(wordLC).length - 1;
    
    return count
};

Cuente el número de subcadenas en una cadena con expresiones regulares {#cuente el número de subcadenas en una cadena con expresiones regulares}

Otro método para contar el número de ocurrencias es usar expresiones regulares (RegEx). Son patrones de caracteres que se utilizan para buscar, hacer coincidir y validar cadenas. Probablemente, el caso de uso más común para las expresiones regulares es validación de formulario: verificar si la cadena es un correo electrónico (válido), un número de teléfono, etc. Pero en este artículo, lo usaremos para contar la cantidad de ocurrencias de una subcadena en una cadena.

If you want to get to know more about regular expressions in JavaScript, you should read our comprehensive guide - "Guía de expresiones regulares y cadenas coincidentes en JavaScript".

En primer lugar, debemos definir una expresión regular que coincida con la subcadena que estamos buscando. Suponiendo que queremos encontrar el número de ocurrencias de la cadena "naranja" en una cadena más grande, nuestra expresión regular se verá de la siguiente manera:

1
let regex = /orange/gi;

En JavaScript, escribimos un patrón de expresión regular entre dos barras diagonales: /patrón/. Opcionalmente, después de la segunda barra inclinada, puede colocar una lista de banderas: caracteres especiales que se usan para alternar el comportamiento predeterminado al hacer coincidir patrones.

Por ejemplo, de forma predeterminada, las expresiones regulares solo coinciden con la primera aparición del patrón en una cadena de búsqueda. Además, la coincidencia distingue entre mayúsculas y minúsculas, lo que quizás no sea lo que queremos al buscar subcadenas. Por eso, presentaremos dos banderas que usaremos para este artículo:

  • g - se asegura de que obtengamos todas las ocurrencias del patrón (no solo la primera)
  • i - se asegura de que la coincidencia sea insensible a mayúsculas y minúsculas

{.icon aria-hidden=“true”}

Nota: Según sus necesidades, puede elegir qué banderas usará. Estos no son obligatorios.

Ahora, usemos una expresión regular creada previamente para contar el número de ocurrencias de la cadena "orange" en myString:

1
2
3
4
5
6
let myString = "John Doe has 5 oranges while Jane Doe has only 2 oranges, Jane gave Mike 1 of her orange so she is now left with only 1 Orange.";

let regex = /orange/gi;
let count = (myString.match(regex) || []).length;

console.log(count); // 4

{.icon aria-hidden=“true”}

Nota: Hemos agregado || [] in devuelve una matriz vacía si no hay ninguna coincidencia. Por lo tanto, el número de ocurrencias se establecerá en 0.

Alternativamente, podemos usar el constructor RegExp() para crear una expresión regular. Acepta un patrón de búsqueda como primer argumento y marca como segundo:

1
2
3
4
5
6
let myString = "John Doe has 5 oranges while Jane Doe has only 2 oranges, Jane gave Mike 1 of her orange so she is now left with only 1 Orange.";

let regex = new RegExp("orange", "gi");
let count = (myString.match(regex) || []).length;

console.log(count); // 4

Además, podemos hacer que esto sea reutilizable envolviéndolo en una función separada:

1
2
3
4
5
let countOcurrences = (str, word) => {
    var regex = new RegExp(word, "gi");
    let count = (str.match(regex) || []).length;
    return count;
};

Concordancia estricta de frases exactas

A veces, desea hacer coincidir una frase o palabra estricta, de modo que "naranjas" no esté incluida en sus recuentos, o cualquier palabra que incluya "naranja" en sí misma, pero no lo esté. t estrictamente "naranja". Este es un caso de uso más específico de búsqueda de cadenas dentro de cadenas y, afortunadamente, ¡es bastante fácil!

1
let regex = /\Worange\W/gi;

Al envolver nuestro término dentro de \W \W, estamos haciendo coincidir estrictamente "naranja" (sin distinción entre mayúsculas y minúsculas) y esta expresión regular coincidiría solo dos veces en nuestra oración (ambas "naranjas" no coinciden).

Rendimiento de evaluación comparativa {#rendimiento de evaluación comparativa}

Cuando ejecutamos ambos métodos usando el Punto de referencia de JS, el método split siempre saldrá más rápido que el método regex, aunque esto no se nota incluso para texto bastante grande corpus Probablemente estarás bien usando cualquiera de los dos.

{.icon aria-hidden=“true”}

Nota: No confíe en estos puntos de referencia como su decisión final. En su lugar, pruébelos usted mismo para determinar cuál es el más adecuado para su caso de uso específico.

Conclusión

En este artículo, aprendimos sobre dos métodos estándar para calcular el número de ocurrencias de subcadenas en una cadena. También evaluamos los resultados, señalando que realmente no importa qué enfoque tome, siempre que funcione para usted.