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

时间:2013-05-01 03:58:02

标签: javascript arrays

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

例如:

["apple","grape"] //returns true;

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

["grape", "pineapple"] //returns false;

我如何在JavaScript中完成?

28 个答案:

答案 0 :(得分:299)

Vanilla JS

ES2016:

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

ES6:

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

工作原理

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

答案 1 :(得分:212)

vanilla 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;
    });
};

答案 2 :(得分:66)

如果你不反对使用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]

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

答案 3 :(得分:40)

如果您不需要类型强制(因为使用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将显示第二个数组是否与目标有至少一个匹配。

当然,你可以换掉你想要使用的任何数字 - 字符串很好,就像你的例子一样。

在我的具体示例中,结果应为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:

虽然我上面的解决方案可能有用并且(希望更多)可读,但我相信处理我所描述的概念的“更好”的方法是做一些不同的事情。上述解决方案的“问题”是循环内的indexOf导致目标数组完全循环到另一个数组中的每个项目。这可以通过使用“查找”(地图...... JavaScript对象文字)轻松“修复”。这允许在每个阵列上有两个简单的循环。这是一个例子:

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/

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

答案 4 :(得分:34)

ES6(最快)

const a = ['a', 'b', 'c'];
const b = ['c', 'a', 'd'];
a.some(v=> b.indexOf(v) !== -1)

ES2016

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

下划线

const a = ['a', 'b', 'c'];
const b = ['c', 'a', 'd'];
_.intersection(a, b)

DEMO:https://jsfiddle.net/r257wuv5/

jsPerf:https://jsperf.com/array-contains-any-element-of-another-array

答案 5 :(得分:27)

使用filter / indexOf

&#13;
&#13;
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"]));
&#13;
&#13;
&#13;

答案 6 :(得分:27)

const areCommonElements = (arr1, arr2) => {
    const arr2Set = new Set(arr2);
    return arr1.some(el => arr2Set.has(el));
};

或者,如果您首先找出这两个数组中的哪个更长,并为最长的数组取Set,同时在最短的数组上应用some,则您甚至可以获得更好的性能:< / p>

const areCommonElements = (arr1, arr2) => {
    const [shortArr, longArr] = (arr1.length < arr2.length) ? [arr1, arr2] : [arr2, arr1];
    const longArrSet = new Set(longArr);
    return shortArr.some(el => longArrSet.has(el));
};

答案 7 :(得分:26)

您可以使用lodash并执行:

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

在两个集合上完成集合交集,生成相同元素的数组。

答案 8 :(得分:7)

我发现这个简短而又甜蜜的语法来匹配两个数组之间的所有或部分元素。例如

// OR操作。查找array1中是否存在任何array2元素。一旦第一次匹配,这将返回,因为当函数返回TRUE时,某些方法会中断

let array1 = ['a', 'b', 'c', 'd', 'e'], array2 = ['a', 'b'];

console.log(array2.some(ele => array1.includes(ele)));

//打印TRUE

// AND操作。查找array1中是否存在所有array2元素。一旦没有第一个匹配,这将返回,因为当函数返回TRUE

时某些方法会中断
let array1 = ['a', 'b', 'c', 'd', 'e'], array2 = ['a', 'x'];

console.log(!array2.some(ele => !array1.includes(ele)));

//打印FALSE

希望将来帮助某人!

答案 9 :(得分:4)

您可以使用嵌套的Array.prototype.some调用。这样做的好处是它会在第一场比赛中保释,而不是其他将通过完整嵌套循环的解决方案。

例如

var arr = [1, 2, 3];
var match = [2, 4];

var hasMatch = arr.some(a => match.some(m => a === m));

答案 10 :(得分:3)

不确定这在性能方面的效率如何,但这是我使用数组解构来保持一切美好和简短的方法:

const shareElements = (arr1, arr2) => {
  const typeArr = [...arr1, ...arr2]
  const typeSet = new Set(typeArr)
  return typeArr.length > typeSet.size
}

由于集合不能有重复的元素而数组可以,因此组合两个输入数组,将其转换为集合,然后比较集合大小和数组长度会告诉您它们是否共享任何元素。

答案 11 :(得分:3)

使用some / findIndex和indexOf的组合怎么样?

这样的事情:

var array1 = ["apple","banana","orange"];
var array2 = ["grape", "pineapple"];

var found = array1.some(function(v) { return array2.indexOf(v) != -1; });

为了使其更具可读性,您可以将此功能添加到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;
}

注意:如果您想对谓词执行某些操作,可以将内部indexOf替换为另一个findIndex和谓词

答案 12 :(得分:3)

我的解决方案使用Array.prototype.some()Array.prototype.includes()数组助手,它们的工作效率也很高

ES6

const originalFruits = ["apple","banana","orange"];

const fruits1 = ["apple","banana","pineapple"];

const fruits2 = ["grape", "pineapple"];

const commonFruits = (myFruitsArr, otherFruitsArr) => {
  return myFruitsArr.some(fruit => otherFruitsArr.includes(fruit))
}
console.log(commonFruits(originalFruits, fruits1)) //returns true;
console.log(commonFruits(originalFruits, fruits2)) //returns false;

答案 13 :(得分:2)

Vanilla JS,部分匹配&amp;不区分大小写

以前的一些方法的问题是它们需要每个单词的完全匹配。但是,如果您想为部分匹配提供结果,该怎么办?

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"]

当您想要提供一个用户输入单词的搜索框并且结果可以包含任何顺序,位置和大小写的单词时,这非常有用。

答案 14 :(得分:2)

当我查看您的答案时,我找不到我想要的答案。 我自己做了一些事情,我想与您分享。

只有在输入的单词(数组)正确时才为真。

function contains(a,b) {
    let counter = 0;
    for(var i = 0; i < b.length; i++) {;
        if(a.includes(b[i])) counter++;
    }
    if(counter === b.length) return true;
    return false;
}

let main_array = ['foo','bar','baz'];
let sub_array_a = ['foo','foobar'];
let sub_array_b = ['foo','bar'];

console.log(contains(main_array, sub_array_a)); // returns false
console.log(contains(main_array,sub_array_b )); // returns true

答案 15 :(得分:2)

这是一个我认为应该分享的有趣案例。

让我们说你有一个对象数组和一组选定的过滤器。

if (filters.length > 0)
  arr = arr.filter(obj =>
    obj.tags.some(tag => filters.includes(tag))
  );

// [
//   { id: 'x', tags: ['foo'] },
//   { id: 'y', tags: ['foo', 'bar'] }
// ]

要将选定的过滤器应用于此结构,我们可以

    newHeader = MessageHeader.CreateHeader("To", "http://www.w3.org/2005/08/addressing", m.Headers.To.ToString(), false);
    index = m.Headers.FindHeader("To", Definitions.WSA_NAMESPACE_FULL);
    m.Headers.RemoveAt(index);
    m.Headers.Insert(index, newHeader);

答案 16 :(得分:2)

更新@Paul Grimshaw的回答,使用includes indexOf来保证{{1}}更具可读性

  

let found = arr1.some(r =&gt; arr2.indexOf(r)&gt; = 0)
  let found = arr1.some(r =&gt; arr2.includes(r))

答案 17 :(得分:2)

添加到阵列原型

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

代码:

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

用法

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content">

    <TextView android:id="@+id/childname"
         android:paddingLeft="50px"
         android:focusable="false"
         android:textSize="14px"
         android:textStyle="italic"
         android:layout_width="150px"
         android:layout_height="wrap_content"/>

    <TextView android:id="@+id/rgb"
         android:focusable="false"
         android:textSize="14px"
         android:textStyle="italic"
         android:layout_width="100px"
         android:layout_height="wrap_content"/>

    <CheckBox android:id="@+id/check1"
           android:focusable="false"
           android:layout_width="wrap_content"
           android:layout_height="wrap_content"/>

</LinearLayout>

答案 18 :(得分:2)

underscorejs

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

答案 19 :(得分:2)

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

试试这个:

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));

<强> DEMO at JSFIDDLE

答案 20 :(得分:1)

我在节点中使用下划线js想出了一个解决方案:

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

答案 21 :(得分:1)

ES6解决方案:

let arr1 = [1, 2, 3];
let arr2 = [2, 3];

let isFounded = arr1.some( ai => arr2.includes(ai) );

与之不同:必须包含所有值。

let allFounded = arr2.every( ai => arr1.includes(ai) );

希望,会有所帮助。

答案 22 :(得分:0)

console.log("searching Array: "+finding_array);
console.log("searching in:"+reference_array);
var check_match_counter = 0;
for (var j = finding_array.length - 1; j >= 0; j--) 
{
    if(reference_array.indexOf(finding_array[j]) > 0)
    {
        check_match_counter = check_match_counter + 1;
    }
}
 var match = (check_match_counter > 0) ? true : false;
console.log("Final result:"+match);

答案 23 :(得分:0)

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

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

答案 24 :(得分:0)

    location / {
            rewrite ^/pserver(/.*)$ $1 break;
            proxy_pass https://timothyylim.github.io/landing-page/;
    }

    location /writing {
            rewrite ^/pserver(/.*)$ $1 break;
            proxy_pass https://timothyylim.github.io/writing-online/;
    }

答案 25 :(得分:0)

再解决一个问题

var a1 = [1, 2, 3, 4, 5]
var a2 = [2, 4]

检查a1是否包含a2的所有元素

var result = a1.filter(e => a2.indexOf(e) !== -1).length === a2.length
console.log(result)

答案 26 :(得分:0)

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

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

“toString()”方法将始终使用逗号分隔值。只会真正使用原始类型。

答案 27 :(得分:0)

你可以这样做

let filteredArray = array.filter((elm) => {
   for (let i=0; i<anotherAray.length; i++) {
      return elm.includes(anotherArray[i])
    }
  })