JavaScript中检查字符串是否包含数组中的任何元素

63

如何检查字符串是否包含数组中的任何元素? 如果元素具有某些字符串,则希望过滤掉一些数组。 请参见以下代码。

var arr = ['banana', 'monkey banana', 'apple', 'kiwi', 'orange'];

function checker(value) {
  var prohibited = ['banana', 'apple'];

  for (var i = 0; i < prohibited.length; i++) {
    if (value.indexOf(prohibited[i]) == -1) {
      return true;
    } else {
      return false;
    }
  }
}

arr = arr.filter(checker);
console.log(arr);

结果是[ 'apple', 'kiwi', 'orange' ]。应该移除'apple',但是没有移除。

上述代码只过滤了'banana',而没有过滤'apple'。我有许多关键字需要过滤。是否有更简单的方法?

8个回答

83

它可以如此简单:

const arr = ['banana', 'monkey banana', 'apple', 'kiwi', 'orange'];

const checker = value =>
  !['banana', 'apple'].some(element => value.includes(element));

console.log(arr.filter(checker));

ECMAScript 6 FTW!

The checker uses 箭头函数.

The ! 表示排除不符合条件的所有元素。

some() 方法测试数组中是否有至少一个元素通过提供的函数实现的测试。

来自MDN 上 Array.prototype.some() 的文档

includes() 方法确定一个字符串是否可以在另一个字符串中找到,根据情况返回 truefalse

来自MDN 上 String.prototype.includes() 的文档


由于某些最新 ECMAScript 特性并非所有浏览器都支持,所以您应使用 Babel 将代码编译为 ECMAScript 5。


如何使用数字数组实现这个?对于数字数组,我得到了“value.includes不是一个函数”的错误。对于value.indexOf(..) != -1也会出现相同的错误。 - Collin

34

问题出现在for循环中,因为return结束函数并在此过程中中断了for循环,所以您可以更新代码,使函数在完成for循环后才返回。

var arr = ['banana', 'monkey banana', 'apple', 'kiwi', 'orange'];

function checker(value) {
  var prohibited = ['banana', 'apple'];

  for (var i = 0; i < prohibited.length; i++) {
    if (value.indexOf(prohibited[i]) > -1) {
      return false;
    }
  }
  return true;
}

arr = arr.filter(checker);
console.log(arr);


为了简化函数,您可以使用every()indexOf()方法。

'every' 方法会对数组中的每个元素执行提供的回调函数,直到找到其中一个回调返回一个假值(转换为布尔值时变为 false)为止。如果找到这样的元素,则 every 方法会立即返回 false。否则,如果所有元素的回调都返回 true 值,则 every 将返回 true。回调仅在具有已分配值的数组索引上调用,而不会在已删除或从未分配值的索引上调用。(摘自此处

var arr = ['banana', 'monkey banana', 'apple', 'kiwi', 'orange'];

function checker(value) {
  var prohibited = ['banana', 'apple'];
  return prohibited.every(function(v) {
    return value.indexOf(v) == -1;
  });
}

arr = arr.filter(checker);
console.log(arr);


对于较旧的浏览器,请检查每个方法的polyfill选项


你甚至可以在这里使用一个正则表达式。使用数组生成正则表达式并使用test()检查匹配。

var arr = ['banana', 'monkey banana', 'apple', 'kiwi', 'orange'];

function checker(value) {
  var prohibited = ['banana', 'apple'];
  var regex = new RegExp(prohibited.map(function(s) {
    return s.replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&')
  }).join('|'));
  return !regex.test(value);
}

arr = arr.filter(checker);
console.log(arr);

参考此答案进行字符串转正则表达式转换:Can you create JavaScript regexes on the fly using string variables?


32
您可以使用 some() 函数:检查字符串中是否包含数组中的任何元素。

例如:

var fruitsArr = ['banana', 'monkey banana', 'apple', 'kiwi', 'orange'];
var myString = "I have an apple and a watermelon.";
var stringIncludesFruit = fruitsArr.some(fruit => myString.includes(fruit));

这个函数还比较新。 some() 方法接受一个回调函数,您可以在其中定义要验证的条件,并返回一个布尔值。请查看上面链接中的文档。


3
这是我最喜欢的答案,因为它写得很好,易于阅读。谢谢。 - Dave

5

对于寻找简单单行代码的人:

arr.filter(item => !prohibited.some(prohb => item.includes(prohb)))  // ["kiwi", "orange"]

4
有人可能会认为这是一个值得商榷的做法,但你可能会发现直接在字符串上运行方法很有用 - 在这种情况下,你可以使用String.prototype扩展JavaScript String对象。

String.prototype.containsAny = String.prototype.containsAny || function(arr) {
  for (var i = 0; i < arr.length; i++) {
    if (this.indexOf(arr[i]) > -1) {
      return true;
    }
  }
  return false;
};

如您在此示例中所见,它将默认使用任何现有的 containsAny 方法定义。请记住:每当您增强内置对象时,至少检查属性是否存在是个好主意 - 也许某一天它会存在... ¯\_(ツ)_/¯ 请查看 这个fiddle 以获取用法或查看下面:

var str = 'This is a sentence as a string.';

console.log(str.containsAny(['string1', 'string2', 'string3'])); // -> returns false
console.log(str.containsAny(['string', 'string1', 'string2'])); // -> returns true
<script src="//cdn.simpledigital.net/common/js/extensions/String.prototypeHelpers.js"></script>


4

我认为这可以大大简化。Javascript内置了检查这些内容的功能。例如:

var arr = ['banana', 'monkey banana', 'apple', 'kiwi', 'orange'];

function checker(value) {
  var prohibited = ['banana', 'apple'];

  // indexOf() returns -1 if the element doesn't exist in the prohibited array
  return prohibited.indexOf( value ) == -1;
}

arr = arr.filter(checker);
console.log(arr);

不幸的是,这种方法与原始方法不同。请注意,在原始方法中,使用*String.prototype.indexOf()进行比较,但这里使用了Array.prototype.indexOf()*。本质上,在原始方法中,对于arr的第二个元素,即猴子香蕉,它调用了'monkey banana'.indexOf('banana'),返回7(然后为prohibited的第二个元素进行第二次调用)。在您的示例中,它调用了['banana', 'apple'].indexOf('monkey banana'),返回-1。 - Elmo Allén

3
    const stringInput = "I have a kiwi";
    const arr = ['banana', 'monkey banana', 'apple', 'kiwi', 'orange'];
    const exists = arr.some((t) => stringInput.indexOf(t) > -1); 
or
    const exists = arr.some((t) => stringInput.includes(t)); 
// iterate through arr items.
// If any of your item is a substring in the input string, then the result of the statement will be `true` otherwise will be `false`.

如需了解有关 some 函数的信息,请查看此参考资料:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/some

如需了解有关 includes 函数的信息,请查看此参考资料:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/includes


虽然这段代码片段可能解决问题,但它并没有解释为什么或如何回答这个问题。请在您的代码中包含解释,因为这真的有助于提高您的帖子质量。记住,您正在回答未来读者的问题,而这些人可能不了解您的代码建议原因。 - Luca Kiebel

0
例如,通过构建一个正则表达式并对其进行测试:
var arr = ['banana', 'monkey banana', 'apple', 'kiwi', 'orange'];
var prohibited = ['banana', 'apple'];

var escapeForRegex = function(str) {
  return String(str).replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1');
};

var r = new RegExp(prohibited.map(escapeForRegex).join("|"));
arr.filter(function(v){ return !r.test(v) });

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