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

7427

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

¿Cuál es una forma razonable de verificar esto?

Peter O.
fuente

Respuestas:

13777

ECMAScript 6 introducido String.prototype.includes:

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

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

includes sin embargo, no tiene soporte para Internet Explorer . En entornos ECMAScript 5 o 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);

Ry-
fuente
25
Tampoco me gusta IE, pero si tiene dos funciones que son en gran medida idénticas, y una es mejor compatible que la otra, ¿creo que debería elegir la mejor compatible? Así indexOf()es ...
rob74
3
¿Es posible hacer una búsqueda insensible a mayúsculas y minúsculas?
Eric McWinNEr
18
string.toUpperCase().includes(substring.toUpperCase())
Rodrigo Pinto
2
@EricMcWinNEr /regexpattern/i.test(str)-> i flag significa insensibilidad a mayúsculas y minúsculas
Code Maniac
Esto no parece funcionar para mí en Google App Script.
Ryan
561

Hay un String.prototype.includesen ES6 :

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

Tenga en cuenta que esto no funciona en Internet Explorer o en otros navegadores antiguos sin compatibilidad con ES6 o incompleta. Para que funcione en navegadores antiguos, es posible que desee utilizar un transpilador como Babel , una biblioteca de 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;
    }
  };
}
eliocs
fuente
3
Solo hazlo "potato".includes("to");y pásalo por Babel.
Derk Jan Speelman
1
tristemente no incluye IE
Sweet Chilly Philly
@eliocs, ¿puedes responder esto? Estoy recibiendo cualquier mensaje. Necesita cambiar el mensaje stackoverflow.com/questions/61273744/…
sejn
1
Otra ventaja es que también distingue entre mayúsculas y minúsculas. "boot".includes("T")esfalse
Jonatas CD
47

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 de los casos O ( n + m ), en comparación con el peor de los casos de O ( nm ) para el algoritmo ingenuo, por lo que usar 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

Mark Amery
fuente
11
Esto es exagerado pero, sin embargo, una respuesta interesante
Faissaloo