Usually I would expect a String.contains()
method, but there doesn't seem to be one.
What is a reasonable way to check for this?
3 Answers 3
ECMAScript 6 introduced String.prototype.includes
:
const string = "foo";
const substring = "oo";
console.log(string.includes(substring)); // true
String.prototype.includes
is case-sensitive and is not supported by Internet Explorer without a polyfill.
In ECMAScript 5 or older environments, use String.prototype.indexOf
, which returns -1 when a substring cannot be found:
var string = "foo";
var substring = "oo";
console.log(string.indexOf(substring) !== -1); // true
-
66While this is a good answer, and the OP never requested for a "case-sensitive" search, it should be noted that
includes
performs a case-sensitive search.Gavin– Gavin2021年06月18日 15:22:54 +00:00Commented Jun 18, 2021 at 15:22 -
11@Aashiq: Yes, an empty string is a substring of every string.2021年09月22日 15:39:13 +00:00Commented Sep 22, 2021 at 15:39
-
12@Gavin by default if I want to know if something is a substring, I imagine it would be case-sensitive. After all, "A" and "a" are different characters. The OP never requested a "case-insensitive" search ( which is a trivial solution, if you make everything lowercase)Davo– Davo2022年01月15日 01:31:03 +00:00Commented Jan 15, 2022 at 1:31
-
19Why is a discussion of case sensitivity even taking place here?KWallace– KWallace2022年06月30日 19:04:57 +00:00Commented Jun 30, 2022 at 19:04
-
4
There is a String.prototype.includes
in ES6:
"potato".includes("to");
> true
Note that this does not work in Internet Explorer or some other old browsers with no or incomplete ES6 support. To make it work in old browsers, you may wish to use a transpiler like Babel, a shim library like es6-shim, or this polyfill from 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;
}
};
}
-
1just curious, why do you need to check the length? Does IE fail in that case or something?user128511– user1285112021年02月02日 15:29:01 +00:00Commented Feb 2, 2021 at 15:29
-
2Also the checking for
number
fails to perform likeincludes
. Example: es6 includes returns false for"abc".includes("ab", "1")
this polyfill will return trueuser128511– user1285112021年02月02日 15:34:57 +00:00Commented Feb 2, 2021 at 15:34 -
I don't think it's easy to use Internet Explorer right now.The Empty String Photographer– The Empty String Photographer2024年09月05日 14:35:04 +00:00Commented Sep 5, 2024 at 14:35
Another alternative is KMP (Knuth–Morris–Pratt).
The KMP algorithm searches for a length-m substring in a length-n string in worst-case O(n+m) time, compared to a worst-case of O(n⋅m) for the naive algorithm, so using KMP may be reasonable if you care about worst-case time complexity.
Here's a JavaScript implementation by Project Nayuki, taken from 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[i] !== pattern[j])
j = lsp[j - 1];
if (pattern[i] === pattern[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[i] != pattern[j])
j = lsp[j - 1]; // Fall back in the pattern
if (text[i] == pattern[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
-
12Not questioning anything on this approach... but why implementing KMP where there's a
includes
orindexOf
on the table. (Although the underneath impl of those maybe using KMP... not sure)sphoenix– sphoenix2021年07月13日 17:00:17 +00:00Commented Jul 13, 2021 at 17:00 -
2KMP provides linear O(n) performance here.wz366– wz3662021年07月15日 17:20:04 +00:00Commented Jul 15, 2021 at 17:20
-
1@wz366 KMP provides O(n), what about the rest? Any Idea?TheLebDev– TheLebDev2021年07月18日 08:12:40 +00:00Commented Jul 18, 2021 at 8:12
-
3If this is used for speed, it would likely run faster if you replaced
.charAt(i)
with[i]
to avoid the extra function calls.dandavis– dandavis2021年08月20日 02:54:27 +00:00Commented Aug 20, 2021 at 2:54 -
899% of the times, doing this is overkill and harmful for non-computational aspects of a software project. Unless you're working on something extremely critical, I strongly advise against following this path... I don't think that big players like Twitter, Facebook, or most of Google products would even use this... so why should you?Clint Eastwood– Clint Eastwood2023年01月11日 19:16:36 +00:00Commented Jan 11, 2023 at 19:16
Explore related questions
See similar questions with these tags.