检查一个数组是否包含JavaScript中另一个数组的任何元素

我有一个目标数组["apple","banana","orange"] ,我想检查是否其他数组包含任何一个目标数组元素。

例如:

 ["apple","grape"] //returns true; ["apple","banana","pineapple"] //returns true; ["grape", "pineapple"] //returns false; 

我怎样才能在JavaScript中做到这一点?

香草js

 /** * @description determine if an array contains one or more items from another array. * @param {array} haystack the array to search. * @param {array} arr the array providing items to check for in the haystack. * @return {boolean} true|false if haystack contains at least one item from arr. */ var findOne = function (haystack, arr) { return arr.some(function (v) { return haystack.indexOf(v) >= 0; }); }; 

如果你不反对使用libray, http ://underscorejs.org/有一个交集方法,可以简化这个:

 var _ = require('underscore'); var target = [ 'apple', 'orange', 'banana']; var fruit2 = [ 'apple', 'orange', 'mango']; var fruit3 = [ 'mango', 'lemon', 'pineapple']; var fruit4 = [ 'orange', 'lemon', 'grapes']; console.log(_.intersection(target, fruit2)); //returns [apple, orange] console.log(_.intersection(target, fruit3)); //returns [] console.log(_.intersection(target, fruit4)); //returns [orange] 

交集函数将返回一个新的数组与它匹配的项目,如果不匹配,则返回空数组。

香草的Javascript

ES2016:

 let found = arr1.some(r=> arr2.includes(r)) 

ES6:

 let found = arr1.some(r=> arr2.indexOf(r) >= 0) 

怎么运行的

Array.prototype.some(..)检查数组的每个元素对testing函数,如果数组的任何元素通过testing函数,则返回true,否则返回false。 indexOf(..) >= 0数组中存在给定的参数, indexOf(..) >= 0includes(..)都返回true。

如果你不需要types强制(因为使用indexOf ),你可以尝试如下所示:

 var arr = [1, 2, 3]; var check = [3, 4]; var found = false; for (var i = 0; i < check.length; i++) { if (arr.indexOf(check[i]) > -1) { found = true; break; } } console.log(found); 

其中arr包含目标项目。 最后, found将显示如果第二个数组至less有一个匹配的目标。

当然,你可以换出任何你想使用的数字 – string是好的,就像你的例子。

在我的具体例子中,结果应该是true因为第二个数组的3存在于目标中。


更新:

下面是我将它组织成一个函数(与以前的一些小的变化):

 var anyMatchInArray = (function () { "use strict"; var targetArray, func; targetArray = ["apple", "banana", "orange"]; func = function (checkerArray) { var found = false; for (var i = 0, j = checkerArray.length; !found && i < j; i++) { if (targetArray.indexOf(checkerArray[i]) > -1) { found = true; } } return found; }; return func; }()); 

DEMO: http : //jsfiddle.net/u8Bzt/

在这种情况下,该函数可以被修改为将targetArray作为参数传入,而不是在闭包中进行硬编码。


UPDATE2:

虽然我上面的解决scheme可能会工作,并可以(可能更多)可读,但我相信处理我所描述的概念的“更好”的方法是做一些不同的事情。 上述解决scheme的“问题”是循环内的indexOf会导致目标数组完全循环到另一个数组中的每个项目。 这可以很容易地通过使用“查找”(一个地图… JavaScript对象文字)“固定”。 这允许两个简单的循环,每个arrays。 这是一个例子:

 var anyMatchInArray = function (target, toMatch) { "use strict"; var found, targetMap, i, j, cur; found = false; targetMap = {}; // Put all values in the `target` array into a map, where // the keys are the values from the array for (i = 0, j = target.length; i < j; i++) { cur = target[i]; targetMap[cur] = true; } // Loop over all items in the `toMatch` array and see if any of // their values are in the map from before for (i = 0, j = toMatch.length; !found && (i < j); i++) { cur = toMatch[i]; found = !!targetMap[cur]; // If found, `targetMap[cur]` will return true, otherwise it // will return `undefined`...that's what the `!!` is for } return found; }; 

DEMO: http : //jsfiddle.net/5Lv9v/

这个解决scheme的缺点是只能使用数字和string(和布尔值)(正确),因为这些值被隐式地转换为string并设置为查找映射的关键字。 对于非文字值,这不是很好/可能/容易完成。

你可以使用lodash并做:

 _.intersection(originalTarget, arrayToCheck).length > 0 

设置交集是在两个集合上生成一个相同元素的数组。

使用filter / indexOf :

 function containsAny(source,target) { var result = source.filter(function(item){ return target.indexOf(item) > -1}); return (result.length > 0); } //results var fruits = ["apple","banana","orange"]; console.log(containsAny(fruits,["apple","grape"])); console.log(containsAny(fruits,["apple","banana","pineapple"])); console.log(containsAny(fruits,["grape", "pineapple"])); 

ES2016

 let a = ['a', 'b', 'c']; let b = ['c', 'a', 'd']; a.some(v => b.includes(v)); 

演示: https : //jsfiddle.net/r257wuv5/

那么使用some / findIndex和indexOf的组合呢?

所以像这样的东西:

 var array1 = ["apple","banana","orange"]; var array2 = ["grape", "pineapple"]; var found = array1.some(function(v) { return array2.indexOf(v) != -1; }); 

为了使其更具可读性,您可以将此function添加到Array对象本身。

 Array.prototype.indexOfAny = function (array) { return this.findIndex(function(v) { return array.indexOf(v) != -1; }); } Array.prototype.containsAny = function (array) { return this.indexOfAny(array) != -1; } 

注意:如果你想用谓词做一些事情,你可以用另一个findIndex和一个谓词来replace内部的indexOf

添加到数组原型

免责声明:许多人强烈build议不要这样做。 唯一真正成为问题的是如果一个库添加了一个具有相同名称的原型函数(performance不同)或类似的东西。

码:

 Array.prototype.containsAny = function(arr) { return this.some( (v) => (arr.indexOf(v) >= 0) ) } 

不使用大箭头function:

 Array.prototype.containsAny = function(arr) { return this.some(function (v) { return arr.indexOf(v) >= 0 }) } 

用法

 var a = ["a","b"] console.log(a.containsAny(["b","z"])) // Outputs true console.log(a.containsAny(["z"])) // Outputs false 

我想出了一个解决scheme,使用下面的这样的下划线js:

 var checkRole = _.intersection(['A','B'], ['A','B','C']); if(!_.isEmpty(checkRole)) { next(); } 

它可以通过遍历主数组迭代来完成,并检查其他数组是否包含任何目标元素。

尝试这个:

 function Check(A) { var myarr = ["apple", "banana", "orange"]; var i, j; var totalmatches = 0; for (i = 0; i < myarr.length; i++) { for (j = 0; j < A.length; ++j) { if (myarr[i] == A[j]) { totalmatches++; } } } if (totalmatches > 0) { return true; } else { return false; } } var fruits1 = new Array("apple", "grape"); alert(Check(fruits1)); var fruits2 = new Array("apple", "banana", "pineapple"); alert(Check(fruits2)); var fruits3 = new Array("grape", "pineapple"); alert(Check(fruits3)); 

在JSFIDDLE演示

用下划线

 var a1 = [1,2,3]; var a2 = [1,2]; _.every(a1, function(e){ return _.include(a2, e); } ); //=> false _.every(a2, function(e){ return _.include(a1, e); } ); //=> true 
 function containsAny(source,target) { var result = source.filter(function(item){ return target.indexOf(item) > -1}); return (result.length > 0); } //results var fruits = ["apple","banana","orange"]; console.log(containsAny(fruits,["apple","grape"])); console.log(containsAny(fruits,["apple","banana","pineapple"])); console.log(containsAny(fruits,["grape", "pineapple"])); 

香草JS部分匹配和不区分大小写

一些以前的方法的问题是,他们需要每个单词精确匹配 。 但是, 如果你想提供部分匹配的结果呢?

 function search(arrayToSearch, wordsToSearch) { arrayToSearch.filter(v => wordsToSearch.every(w => v.toLowerCase().split(" "). reduce((isIn, h) => isIn || String(h).indexOf(w) >= 0, false) ) ) } //Usage var myArray = ["Attach tag", "Attaching tags", "Blah blah blah"]; var searchText = "Tag attach"; var searchArr = searchText.toLowerCase().split(" "); //["tag", "attach"] var matches = search(myArray, searchArr); //Will return //["Attach tag", "Attaching tags"] 

当你想提供一个用户input单词的search框,并且结果可以以任何顺序,位置和大小写的forms包含这些单词时,这是非常有用的。

就个人而言,我会使用以下function:

 var arrayContains = function(array, toMatch) { var arrayAsString = array.toString(); return (arrayAsString.indexOf(','+toMatch+',') >-1); } 

“toString()”方法将始终使用逗号分隔这些值。 只会真正与原始types一起工作。

对.find()进行嵌套调用的Array .filter()将返回第一个数组中所有属于第二个数组成员的元素。 检查返回数组的长度,以确定是否有第二个数组在第一个数组中。

 getCommonItems(firstArray, secondArray) { return firstArray.filter((firstArrayItem) => { return secondArray.find((secondArrayItem) => { return firstArrayItem === secondArrayItem; }); }); }