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

7418

Por lo general, esperaría un String.contains()método, pero no parece haberlo.

¿Cuál es una forma razonable de comprobarlo?

0
14773

Se presentó ECMAScript 6 String.prototype.includes:

const string = "foo";
const substring = "oo";

console.log(string.includes(substring));

includes sin embargo, no es compatible con Internet Explorer . En ECMAScript 5 o entornos anteriores, use String.prototype.indexOf, que devuelve -1 cuando no se puede encontrar una subcadena:

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

console.log(string.indexOf(substring) !== -1);
1
  • 5
    Si bien esta es una buena respuesta, y el OP nunca solicitó una búsqueda "sensible a mayúsculas y minúsculas", debe tenerse en cuenta que includesrealiza una búsqueda sensible a mayúsculas y minúsculas .
    Gavin
    18 de junio a las 15:22
676

Hay un String.prototype.includesen ES6 :

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

Tenga en cuenta que esto no funciona en Internet Explorer o en algunos otros navegadores antiguos que no tienen soporte para ES6 o éste es incompleto. Para que funcione en navegadores antiguos, es posible que desee utilizar un transpilador como Babel , una biblioteca shim como es6-shim o este 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;
    }
  };
}
2
  • solo curiosidad, ¿por qué necesitas comprobar la longitud? ¿IE falla en ese caso o algo así?
    gman
    2 de febrero a las 15:29
  • 1
    Además, la comprobación numberno funciona como includes. Ejemplo: es6 incluye devuelve falso para "abc".includes("ab", "1")este polyfill devolverá verdadero
    gman
    2 feb a las 15:34
83

Otra alternativa es KMP (Knuth-Morris-Pratt).

El algoritmo KMP busca una subcadena de longitud- m en una cadena de longitud- n en el peor caso de tiempo O ( n + m ), en comparación con el peor caso de O ( nm ) para el algoritmo ingenuo, por lo que el uso de KMP puede Sea razonable si le preocupa la complejidad del tiempo en el peor de los casos.

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

// Searches for the given pattern string in the given text string using the Knuth-Morris-Pratt string matching algorithm.
// If the pattern is found, this returns the index of the start of the earliest match in 'text'. Otherwise -1 is returned.

function kmpSearch(pattern, text) {
  if (pattern.length == 0)
    return 0; // Immediate match

  // Compute longest suffix-prefix table
  var lsp = [0]; // Base case
  for (var i = 1; i < pattern.length; i++) {
    var j = lsp[i - 1]; // Start by assuming we're extending the previous LSP
    while (j > 0 && pattern.charAt(i) != pattern.charAt(j))
      j = lsp[j - 1];
    if (pattern.charAt(i) == pattern.charAt(j))
      j++;
    lsp.push(j);
  }

  // Walk through text string
  var j = 0; // Number of chars matched in pattern
  for (var i = 0; i < text.length; i++) {
    while (j > 0 && text.charAt(i) != pattern.charAt(j))
      j = lsp[j - 1]; // Fall back in the pattern
    if (text.charAt(i) == pattern.charAt(j)) {
      j++; // Next char matched, increment position
      if (j == pattern.length)
        return i - (j - 1);
    }
  }
  return -1; // Not found
}

console.log(kmpSearch('ays', 'haystack') != -1) // true
console.log(kmpSearch('asdf', 'haystack') != -1) // false
4
  • Sin cuestionar nada sobre este enfoque ... pero por qué implementar KMP donde hay un includeso indexOfsobre la mesa. (Aunque el implícito de aquellos que quizás usen KMP ... no estoy seguro) 13 jul a las 17:00
  • KMP proporciona aquí un rendimiento lineal de O (n).
    wz366
    15 de julio a las 17:20
  • @ wz366 KMP proporciona O (n), ¿qué pasa con el resto? ¿Alguna idea? 18 de julio a las 8:12
  • Si se usa para aumentar la velocidad, es probable que se ejecute más rápido si lo reemplaza .charAt(i)con [i]para evitar las llamadas de función adicionales. 20 de agosto a las 2:54