Comment vérifier si une chaîne contient une sous-chaîne en JavaScript?

7427

Habituellement, je m'attendrais à une String.contains()méthode, mais il ne semble pas y en avoir une.

Quelle est une façon raisonnable de vérifier cela?

Peter O.
la source

Réponses:

13778

ECMAScript 6 a introduit String.prototype.includes:

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

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

includes ne prend pas en charge Internet Explorer , cependant. Dans les environnements ECMAScript 5 ou plus anciens, utilisez String.prototype.indexOf, qui renvoie -1 lorsqu'une sous-chaîne est introuvable:

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

console.log(string.indexOf(substring) !== -1);

Ry-
la source
25
Je n'aime pas non plus IE, mais si vous avez deux fonctions qui sont largement identiques et que l'une est mieux prise en charge que l'autre, je pense que vous devriez choisir la meilleure prise en charge? Il indexOf()en est ainsi ...
rob74
3
Est-il possible de faire une recherche insensible à la casse?
Eric McWinNEr le
18
string.toUpperCase().includes(substring.toUpperCase())
Rodrigo Pinto
2
@EricMcWinNEr /regexpattern/i.test(str)-> i flag signifie insensibilité à la casse
Code Maniac
Cela ne semble pas fonctionner pour moi dans Google App Script.
Ryan
561

Il y a un String.prototype.includesdans ES6 :

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

Notez que cela ne fonctionne pas dans Internet Explorer ou dans certains anciens navigateurs sans prise en charge ES6 inexistante ou incomplète. Pour le faire fonctionner dans les anciens navigateurs, vous pouvez utiliser un transpilateur comme Babel , une bibliothèque de shim comme es6-shim , ou ce 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
la source
3
Faites-le "potato".includes("to");et exécutez-le via Babel.
Derk Jan Speelman
1
inclut n'est malheureusement pas pris en charge par IE
Sweet Chilly Philly
@eliocs pouvez-vous répondre à cela. Je reçois un seul message. Besoin de changer le message stackoverflow.com/questions/61273744/…
sejn
1
un autre avantage car il est également sensible à la casse. "boot".includes("T")estfalse
Jonatas CD
47

Une autre alternative est KMP (Knuth – Morris – Pratt).

L'algorithme KMP recherche une sous-chaîne de longueur m dans une chaîne de longueur n dans le pire des cas O ( n + m ), par rapport au pire des cas O ( nm ) pour l'algorithme naïf, donc l'utilisation de KMP peut soyez raisonnable si vous vous souciez de la complexité du pire des cas.

Voici une implémentation JavaScript par Project Nayuki, tirée 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
la source
11
C'est exagéré mais néanmoins une réponse intéressante
Faissaloo