如何在JavaScript中检查字符串是否包含来自子字符串数组的文本?

318

很简单。在JavaScript中,我需要检查一个字符串是否包含数组中包含的任何子字符串。


在新的HTML5-JavaScript版本中,难道没有map()函数吗?我记得曾经读过相关的内容... - Martin Hennings
@Martin:说得好,不是“map”,而是“some”。使用“some”会有所帮助,但你需要传递一个函数。 - T.J. Crowder
24个回答

463

没有内置的方法可以为您完成此操作,您必须编写一个函数,尽管它可以只是some数组方法的回调函数。

你有两种方法:

  • Array some 方法
  • 正则表达式

Array some

数组some方法(在ES5中添加)使这变得非常简单:

if (substrings.some(function(v) { return str.indexOf(v) >= 0; })) {
    // There's at least one
}

使用箭头函数和新的includes方法(ES2015+)会更好:

if (substrings.some(v => str.includes(v))) {
    // There's at least one
}

实时示例:

const substrings = ["one", "two", "three"];
let str;

// Setup
console.log(`Substrings: ${substrings}`);

// Try it where we expect a match
str = "this has one";
if (substrings.some(v => str.includes(v))) {
    console.log(`Match using "${str}"`);
} else {
    console.log(`No match using "${str}"`);
}

// Try it where we DON'T expect a match
str = "this doesn't have any";
if (substrings.some(v => str.includes(v))) {
    console.log(`Match using "${str}"`);
} else {
    console.log(`No match using "${str}"`);
}

正则表达式

如果你确定字符串中不包含正则表达式中特殊字符,那么你可以这样轻松应付:

if (new RegExp(substrings.join("|")).test(string)) {
    // At least one match
}

...这将创建一个正则表达式,其中包含一系列交替项,用于查找您要查找的子字符串(例如,one|two),并测试是否存在任何匹配项,但如果任何子字符串包含在正则表达式中是特殊字符(例如*[等),您必须首先对它们进行转义,最好只是做无聊的循环。有关转义它们的信息,请参见此问题的答案

实时示例:

const substrings = ["one", "two", "three"];
let str;

// Setup
console.log(`Substrings: ${substrings}`);

// Try it where we expect a match
str = "this has one";
if (new RegExp(substrings.join("|")).test(str)) {
    console.log(`Match using "${str}"`);
} else {
    console.log(`No match using "${str}"`);
}

// Try it where we DON'T expect a match
str = "this doesn't have any";
if (new RegExp(substrings.join("|")).test(str)) {
    console.log(`Match using "${str}"`);
} else {
    console.log(`No match using "${str}"`);
}


1
使用.some,你如何返回匹配的那个? - Sergino
1
@sreginogemoh - 在这种情况下,您不会使用 some,而是使用 find,它返回第一个使您的回调函数返回 truthy 值的元素,如果回调从未返回 truthy 值,则返回 undefined - T.J. Crowder
是的,那就是我所做的,不过我认为 some 可能会处理那个问题... - Sergino
1
@sreginogemoh - 只有当你做类似于 let x; if (array.some((v) => { if (/*... v matches condition ... */) { x = v; return true; } return false; })) { /*... use x here ... */ } 这样的事情时,才需要这么做。但在这种情况下,使用 find 更简单、更符合习惯。我展示的唯一真正的原因是当 undefined 实际上在数组中 并且 它是你想要找到的内容时。(使用 find 你不会知道是否已经找到它,或者没有找到任何东西。而使用上述方法,你可以区分出来)。非常罕见的情况... - T.J. Crowder
find/some和includes比其他解决方案要快一些(不多),除了RegExp可能会慢2倍。 - Gage

129
一行解决方案
substringsArray.some(substring=>yourBigString.includes(substring))

如果子字符串存在,则返回true/false。
需要ES6支持。

45
小孩子们……在我小时候,我们必须使用叫做“for”循环的东西,你必须使用多行代码并知道你的数组是基于0还是1的,是的……一半的时间你会搞错,必须调试并注意一个叫做“i”的小家伙。 - aamarks
3
@aamarks“那些金色的日子......” - Syed M. Sannan
2
我喜欢简短的回答。 - YTG

56
var yourstring = 'tasty food'; // the string to check against


var substrings = ['foo','bar'],
    length = substrings.length;
while(length--) {
   if (yourstring.indexOf(substrings[length])!=-1) {
       // one of the substrings is in yourstring
   }
}

30
function containsAny(str, substrings) {
    for (var i = 0; i != substrings.length; i++) {
       var substring = substrings[i];
       if (str.indexOf(substring) != - 1) {
         return substring;
       }
    }
    return null; 
}

var result = containsAny("defg", ["ab", "cd", "ef"]);
console.log("String was found in substring " + result);

1
此外,它返回字符串中第一次出现的单词,这非常有帮助。不仅仅是真/假。 - Avatar
ES6的等价物是什么? - Ridhwaan Shakeel

24

对于正在谷歌搜索的人,

正确的答案应该是。

const substrings = ['connect', 'ready'];
const str = 'disconnect';
if (substrings.some(v => str === v)) {
   // Will only return when the `str` is included in the `substrings`
}

3
如果(substrings.some(v => v===str)){ - kofifus
21
注意,这是对一个略微不同问题的回答,该问题询问一个字符串是否包含来自子字符串数组的文本。这段代码检查一个字符串是否为其中一个子字符串。我想这取决于“包含”的意思。 - fcrick

21

以下是我认为迄今为止最佳解决方案的内容(仅代表个人意见)。它是一种现代化的(ES6)方案,具有以下特点:

  • 效率高(只需一行代码!)
  • 避免使用for循环
  • 与其他答案中使用的some()函数不同,该方法不仅返回布尔值(true/false)
  • 相反,如果在数组中找到了子字符串,则返回该子字符串;否则,返回undefined。
  • 更进一步,它允许您选择是否需要部分子字符串匹配(下面有示例)

享受吧!



const arrayOfStrings = ['abc', 'def', 'xyz'];
const str = 'abc';
const found = arrayOfStrings.find(v => (str === v));

在这种情况下,found将被设置为“abc”。这将适用于精确字符串匹配。

如果您改用:

const found = arrayOfStrings.find(v => str.includes(v));

在这种情况下,found 将再次被设置为 'abc'。这不允许部分匹配,因此如果 str 被设置为 'ab',found 将未定义。


如果您想使部分匹配起作用,只需将其翻转,这样做:

const found = arrayOfStrings.find(v => v.includes(str));

相反,如果str设置为'ab',则found将设置为'abc'。

非常简单!




8
var str = "texttexttext";
var arr = ["asd", "ghj", "xtte"];
for (var i = 0, len = arr.length; i < len; ++i) {
    if (str.indexOf(arr[i]) != -1) {
        // str contains arr[i]
    }
}

编辑:如果测试的顺序不重要,您可以使用以下代码(只有一个循环变量):
var str = "texttexttext";
var arr = ["asd", "ghj", "xtte"];
for (var i = arr.length - 1; i >= 0; --i) {
    if (str.indexOf(arr[i]) != -1) {
        // str contains arr[i]
    }
}

你的第一个例子不需要 len 变量,只需检查 i < arr.length 即可。 - GreySage
这个答案只返回匹配的数组字符串。出于完整性考虑,这应该包含在先前的示例中。 - Justin Farrugia

5

const str = 'Does this string have one or more strings from the array below?';
const arr = ['one', 'two', 'three'];

const contains = arr.some(element => {
  if (str.includes(element)) {
    return true;
  }
  return false;
});

console.log(contains); // true


更短的方法:arr.some(element => str.includes(element) ? true : false) - jasonleonhard

4
substringsArray.every(substring=>yourBigString.indexOf(substring) === -1)

完全支持;)


4

对于完整的支持(除了@ricca的版本)。

wordsArray = ['hello', 'to', 'nice', 'day']
yourString = 'Hello. Today is a nice day'.toLowerCase()
result = wordsArray.every(w => yourString.includes(w))
console.log('result:', result)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接