¿Cómo comprobar si una cadena contiene una subcadena en JavaScript?

Normalmente esperaría un método String.contains()

Pero no parece haber uno.

¿Cuál es la manera razonable de verificar eso?

  • javascript
  • string
  • substring
  • string-matching
3 Repuestas

String#includes()

ES6 introducido String.prototype.includes:

var string = "foo",
 substring = "oo";
 string.includes(substring)

Pero includes no tiene supporto en IE.

String#indexOf()

En un ES5 medioambientes más antiguos String.prototype.indexOf regrese el indice de la cadena (o -1 si no se encuentra):

var string = "foo",
 substring = "oo";

 string.indexOf(substring) !== -1

RegExp#test()

Los usuarios más avanzados podrían RegExp#test, el cual permite verificar en contra de expresiones regulares.

var string = "foo",
 regex = /oo/;

 regex.test(string);

Hay un String.prototype.includes en ES6:

"potato".includes("to");
 > true

Ten en cuenta que esto no funciona en Internet Explorer o en algunos navegadores antiguos on o sin soporte incompleto de ES6. Para que funcione en navegadores antiguos, es posible que desees utilizar un transpiler como Babel, una librería shim como es6-shim, o esto polyfill de MDN:

if (!String.prototype.includes) {
  String.prototype.includes = function(search, start) {
    'use strict';
    if (typeof start !== 'number') {
      start = 0;
    }

    if (start + search.length > this.length) {
      return false;
    } else {
      return this.indexOf(search, start) !== -1;
    }
  };
}

Otra alternativa es KMP.

El algoritmo KMP busca una subcadena de longitud m en una cadena de longitud -n en el peor de los casos O (n+m) para el algoritmo naive, por lo que el uso de KMP puede ser razonable si te importa la complejidad del tiempo.

Aquí hay una implementación de JavaScript para el Proyecto Nayuki, tomada de https://www.nayuki.io/res/knuth-morris-pratt-string-matching/kmp-string-matcher.js:

// busca la cadena del pareon dado en la cadena del texto daro usando la cadena Knuth-Morris-Pratt coincidiendo con el algoritmo.
// si el patrón es encontrado, esto vuelve al índice del comienzo de la coincidencia previa en el "texto". De otro manere -1 es devuelto.
function kmpSearch(pattern, text) {
    if (pattern.length == 0)
        return 0;  // Coincidencia inmediata

    // Calcula la tabla más larga de sufijo-prefijo
    var lsp = [0];  // Caso base
    for (var i = 1; i < pattern.length; i++) {
        var j = lsp[i - 1];  // Comienza asumiendo que estamos extendiendo el LSP previo
        while (j > 0 && pattern.charAt(i) != pattern.charAt(j))
            j = lsp[j - 1];
        if (pattern.charAt(i) == pattern.charAt(j))
            j++;
        lsp.push(j);
    }

    // camina a través de la cadena de texto
    var j = 0;  // Número de caracteres combinados en el patrón
    for (var i = 0; i < text.length; i++) {
        while (j > 0 && text.charAt(i) != pattern.charAt(j))
            j = lsp[j - 1];  // Retrocede en el patrón
        if (text.charAt(i) == pattern.charAt(j)) {
            j++;  // Siguiente char emparejado, incrementa la posición
            if (j == pattern.length)
                return i - (j - 1);
        }
    }
    return -1;  // No encontrado
}

Ejemplo de uso:

kmpSearch('ays', 'haystack') != -1 // true
 kmpSearch('asdf', 'haystack') != -1 // false