902

I have a target array ["apple","banana","orange"], and I want to check if other arrays contain any one of the target array elements.

For example:

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

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

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

How can I do it in JavaScript?

shA.t
  • 16,580
  • 5
  • 54
  • 111
Alex
  • 11,551
  • 13
  • 30
  • 38
  • 5
    Use a `for` loop and iterate over the target array. If every element is contained within the current array (use `current.indexOf(elem) !== -1)`, then they're all in there. – Blender May 01 '13 at 03:59
  • 4
    @LeonGaban I disagree. I wouldn't import a library just to perform this operation. – Patricio Vargas May 08 '20 at 06:40
  • 3
    @devpato yeah changed my mind, the ES6 solution is my fav – Leon Gaban May 12 '20 at 19:31
  • Just in case if you want to get the elements rather than just `true` or `false` then you need to use `.filter()` :: [Javascript algorithm to find elements in array that are not in another array](https://stackoverflow.com/questions/2963281/javascript-algorithm-to-find-elements-in-array-that-are-not-in-another-array) – whoami - fakeFaceTrueSoul Jul 09 '20 at 14:52

32 Answers32

1288

Vanilla JS

ES2016:

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

ES6:

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

How it works

some(..) checks each element of the array against a test function and returns true if any element of the array passes the test function, otherwise, it returns false. indexOf(..) >= 0 and includes(..) both return true if the given argument is present in the array.

Paul Grimshaw
  • 19,894
  • 6
  • 40
  • 59
  • 1
    Is it expected that my result is `[false, false, false]`instead of an empty array`[]`? – Batman Sep 24 '18 at 08:00
  • @Batman: The result is true/false, but you can adapt the solution from Mr. skyisred – 0zkr PM Jun 19 '19 at 22:58
  • 1
    Had to do this to filter down a huge csv looking for something. I used `.filter()` to get a list of the rows that were applicable to the task at hand, and the `some()` method came in handy. Thank you. `var searchTerms = ['term1', 'term2', 'term3', 'term4'];` `var results = csvRows.filter(row => searchTerms.some(value => row.column1.includes(value)));` – Chazt3n Jan 13 '20 at 23:49
  • 1
    How can I get the value of that number? – huykon225 Apr 02 '20 at 16:03
  • @CarloFontanos Does anyone still use IE? – Rodrigo May 19 '21 at 07:37
  • 9
    arr1 and arr2 are terrible names for the purpose of teaching – Max Jan 21 '22 at 13:10
  • how would we go further as to determine or return the similar values that matched between the two arrays? – Gel Jan 25 '22 at 15:05
340

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

As noted by @loganfsmyth you can shorten it in ES2016 to

/**
 * @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.
 */
const findOne = (haystack, arr) => {
    return arr.some(v => haystack.includes(v));
};

or simply as arr.some(v => haystack.includes(v));

If you want to determine if the array has all the items from the other array, replace some() to every() or as arr.every(v => haystack.includes(v));

Xotabu4
  • 3,063
  • 17
  • 29
skyisred
  • 6,855
  • 6
  • 37
  • 54
146

ES6 solution:

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

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

Alternatively, if must contain all values:

let allFound = arr2.every( ai => arr1.includes(ai) );
Phil
  • 7,065
  • 8
  • 49
  • 91
protanvir993
  • 2,759
  • 1
  • 20
  • 17
  • Is there any way to get index of *arra2* values from *array1*?? – Anzil khaN Jul 31 '19 at 09:17
  • 1
    In that case, we can use "filter" instead of "some". Then it'll return an array instead of boolean and you can easily access value from there. – protanvir993 Aug 07 '19 at 06:50
  • 2
    In my case, it only worked if I returned from within the function, e.g.: `let allFounded = arr2.every( ai => return arr1.includes(ai) );` – Fed C Aug 06 '20 at 13:11
81

If you're not opposed to using a libray, http://underscorejs.org/ has an intersection method, which can simplify this:

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]

The intersection function will return a new array with the items that it matched and if not matches it returns empty array.

willz
  • 2,020
  • 3
  • 21
  • 24
  • 4
    I've used this several times, but note that the question was about checking *if* any element exists in the other array, not to produce the entire intersection. In terms of performance there is a huge difference if the arrays are large since in the first case you can bail out as soon as you've found one match. – JHH Jan 22 '16 at 08:35
  • 1
    lodash is much more readable then vanilla Javascript, libs like it at Ramda should always be used instead of vanilla imho. Better for all devs... – Leon Gaban Aug 15 '16 at 20:32
  • Use this in conjunction with `_.some()` i.e. `_.some(_.intersection(target, fruit2))` – Quitch Dec 23 '21 at 15:49
  • Or maybe `_.isEmpty(_.intersection(target, fruit2))`. Thanks @willz – Jose Velasco Apr 27 '22 at 04:32
74

ES6 (fastest)

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

Underscore

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

lusk
  • 749
  • 5
  • 3
53

If you don't need type coercion (because of the use of indexOf), you could try something like the following:

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

Where arr contains the target items. At the end, found will show if the second array had at least one match against the target.

Of course, you can swap out numbers for anything you want to use - strings are fine, like your example.

And in my specific example, the result should be true because the second array's 3 exists in the target.


UPDATE:

Here's how I'd organize it into a function (with some minor changes from before):

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/

In this case, the function could be modified to have targetArray be passed in as an argument instead of hardcoded in the closure.


UPDATE2:

While my solution above may work and be (hopefully more) readable, I believe the "better" way to handle the concept I described is to do something a little differently. The "problem" with the above solution is that the indexOf inside the loop causes the target array to be looped over completely for every item in the other array. This can easily be "fixed" by using a "lookup" (a map...a JavaScript object literal). This allows two simple loops, over each array. Here's an example:

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/

The downside to this solution is that only numbers and strings (and booleans) can be used (correctly), because the values are (implicitly) converted to strings and set as the keys to the lookup map. This isn't exactly good/possible/easily done for non-literal values.

Ian
  • 50,146
  • 13
  • 101
  • 111
  • Why are you using for loops while you could use some or findIndex? – It's me ... Alex Oct 24 '14 at 11:59
  • 1
    "some" simplifies the code greatly. Also, anyMatchInArray([1,2,3,"cats","4"], ["1",4]) would be true. Lastly, this may be more performant IF you had a large number of lookups and cached the targetMap. Even so, there could probably be performance increases. For example, I would guess that "found = toMatch[i] !== undefined" would be more performant, and in some cases better (so that you don't evaluate "" or 0 to false) – csga5000 Jan 12 '16 at 20:17
  • "otherwise it will return `undefined`...that's what the `!!` is for" - that's wrong. It will return the boolean opposition of `!`. – AlienWebguy Sep 30 '17 at 14:42
34

Using 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"]));
Akshay
  • 14,138
  • 5
  • 46
  • 70
Vadim Gremyachev
  • 57,952
  • 20
  • 129
  • 193
  • This suffers from the same problem as library functions such as _.intersection in that it will continue looking for matches even after finding one. For small arrays obviously it doesn't matter though. – JHH Jan 22 '16 at 08:37
32

You could use lodash and do:

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

Set intersection is done on both collections producing an array of identical elements.

Justin Cuaresma
  • 459
  • 5
  • 7
  • It's not optimal in terms of performance, since for this problem it's enough to find the first match, while `intersection` will keep comparing even after finding the first match in order to find all of them. It's like using `filter` when you need just `find`. – Alexander Jun 08 '20 at 15:56
30
const areCommonElements = (arr1, arr2) => {
    const arr2Set = new Set(arr2);
    return arr1.some(el => arr2Set.has(el));
};

Or you can even have a better performance if you first find out which of these two arrays is longer and making Set out for the longest array, while applying some method on the shortest one:

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));
};
Alexander
  • 7,484
  • 4
  • 51
  • 65
  • 4
    While people keep posting solutions with nesting `indexOf` and `includes`, you are the first to answer with the more efficient set-based solution, using the native `Set`, 4 years after it was introduced into EcmaScript. +1 – trincot Feb 16 '20 at 10:19
  • Correct me if I'm wrong, but doesn't creating a Set still require iteration (behind the scenes)? If so, then it wouldn't matter which array is shorter or longer, because the time complexity would still be the same. Yes or no?? – Molasses Feb 06 '21 at 09:05
  • @Sal_Vader_808, as far as I know - this conversion (new Set([])) is very efficient (better that JS code iterating over the array), because it's native code. You can try and create a set using forEach and using Set constructor on a very large arrays and measure the times it takes – Alexander Feb 08 '21 at 13:19
  • @Alexander While I agree that putting it in a `Set` would greatly improve the time complexity (similar to @devpato "USING MAPS" answer) going from O(n^2) to O(n), I'm not sure what you mean by "it's native code". It's still Javascript, right? It's not like you're calling some other compiled language when you call `Set` (https://tc39.es/ecma262/#sec-set-constructor). Also, as I mentioned in my comment on @devpato 's answer, I don't believe that determining the long and short array will improve the algorithm. You will still iterate both arrays. Just my $0.02. – Molasses Feb 08 '21 at 14:10
  • 1
    @Sal_Vader_808 I actually mean that it is compiled (implemented in the browser's compiled code instead of a JS loop being run by an interpreter). Try to write `Set` in the browser console and then hit the Enter key. You will get this response: `ƒ Set() { [native code] }` instead of the JS code of its implementation. While some of the native code can be slower and that's only because some of it has lots of extra validators. – Alexander Feb 11 '21 at 16:40
  • 1
    *Remark*: obviously, the array length is not the only factor for making the decision which array should be converted into a Set. It depends on the code, e.g. if it always checks the same array for common elements with many other different arrays - you will apparently want to convert it into a Set just once and store it in a constant outside of the function even it's not the longest one. – Alexander Feb 11 '21 at 16:50
  • 1
    @Alexander Cool! It looks like it is native code. Learned something new again, thanks! Also, yes, definitely should consider caching data if it's expected to be used multiple times. Memoization FTW! – Molasses Feb 13 '21 at 01:10
22

I wrote 3 solutions. Essentially they do the same. They return true as soon as they get true. I wrote the 3 solutions just for showing 3 different way to do things. Now, it depends what you like more. You can use performance.now() to check the performance of one solution or the other. In my solutions I'm also checking which array is the biggest and which one is the smallest to make the operations more efficient.

The 3rd solution may not be the cutest but is efficient. I decided to add it because in some coding interviews you are not allowed to use built-in methods.

Lastly, sure...we can come up with a solution with 2 NESTED for loops (the brute force way) but you want to avoid that because the time complexity is bad O(n^2).

Note:

instead of using .includes() like some other people did, you can use .indexOf(). if you do just check if the value is bigger than 0. If the value doesn't exist will give you -1. if it does exist, it will give you greater than 0.

indexOf() vs includes()

Which one has better performance? indexOf() for a little bit, but includes is more readable in my opinion.

If I'm not mistaken .includes() and indexOf() use loops behind the scene, so you will be at O(n^2) when using them with .some().

USING loop

 const compareArraysWithIncludes = (arr1, arr2) => {
     const [smallArray, bigArray] =
        arr1.length < arr2.length ? [arr1, arr2] : [arr2, arr1];

     for (let i = 0; i < smallArray.length; i++) {
       return bigArray.includes(smallArray[i]);
     }

      return false;
    };

USING .some()

const compareArraysWithSome = (arr1, arr2) => {
  const [smallArray, bigArray] =
    arr1.length < arr2.length ? [arr1, arr2] : [arr2, arr1];
  return smallArray.some(c => bigArray.includes(c));
};

USING MAPS Time complexity O(2n)=>O(n)

const compararArraysUsingObjs = (arr1, arr2) => {
  const map = {};

  const [smallArray, bigArray] =
    arr1.length < arr2.length ? [arr1, arr2] : [arr2, arr1];

  for (let i = 0; i < smallArray.length; i++) {
    if (!map[smallArray[i]]) {
      map[smallArray[i]] = true;
    }
  }

  for (let i = 0; i < bigArray.length; i++) {
    if (map[bigArray[i]]) {
      return true;
    }
  }

  return false;
};

Code in my: stackblitz

I'm not an expert in performance nor BigO so if something that I said is wrong let me know.

Patricio Vargas
  • 5,236
  • 11
  • 49
  • 100
  • Good answer, but: "If you [use indexOf] just check if the value is bigger than 0. If the value doesn't exist will give you -1. if it does exist, it will give you greater than 0." This should read bigger than *or equal to* / greater than *or equal to*. – angus l Jul 25 '20 at 18:31
  • 2
    With regards to using includes, I don't think determining which array is shorter/longer matters. Looking at how `Array#includes` is implemented (tc39.es/ecma262/#sec-array.prototype.includes), it still looks like you'll have to iterate through the longer array. Unless I read the implementation of `includes` all wrong (which is possible haha). Also, I agree that using maps would be the most efficient. – Molasses Feb 06 '21 at 09:19
  • HI @Sal_Vader_808 good point. Let me do some research. Thank you! – Patricio Vargas Feb 07 '21 at 07:15
  • Thank you for this bit of code! This helped out greatly with my project. If it wouldn't be too much to ask, is there a way to show which terms are the same between the two arrays with your `.some()` solution? – Jonathin Apr 18 '21 at 22:02
10

I found this short and sweet syntax to match all or some elements between two arrays. For example

// OR operation. find if any of array2 elements exists in array1. This will return as soon as there is a first match as some method breaks when function returns TRUE

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

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

// prints TRUE

// AND operation. find if all of array2 elements exists in array1. This will return as soon as there is a no first match as some method breaks when function returns TRUE

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

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

// prints FALSE

Hope that helps someone in future!

kashpatel
  • 696
  • 1
  • 6
  • 18
  • I really liked the second part of the question, to make it work for ES5, did it like: !array2.some( function(ele) {return array1.indexOf(ele) === -1 }); – Friesgaard Jun 19 '18 at 18:09
9

You can use a nested Array.prototype.some call. This has the benefit that it will bail at the first match instead of other solutions that will run through the full nested loop.

eg.

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

var hasMatch = arr.some(a => match.some(m => a === m));
bingles
  • 11,582
  • 10
  • 82
  • 93
8

Just one more solution

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

Check if a1 contain all element of a2

var result = a1.filter(e => a2.indexOf(e) !== -1).length === a2.length
console.log(result)
Cong Nguyen
  • 3,199
  • 1
  • 23
  • 22
  • 1
    To improve upon this, we can use the filter loop on the shortest length of array instead. `const result = a2.filter((e) => a1.indexOf(e) !== -1).length === a2.length;` – Badal Saibo Nov 16 '20 at 06:45
7

What about using a combination of some/findIndex and indexOf?

So something like this:

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

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

To make it more readable you could add this functionality to the Array object itself.

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

Note: If you'd want to do something with a predicate you could replace the inner indexOf with another findIndex and a predicate

It's me ... Alex
  • 279
  • 4
  • 11
6

Here is an interesting case I thought I should share.

Let's say that you have an array of objects and an array of selected filters.

let arr = [
  { id: 'x', tags: ['foo'] },
  { id: 'y', tags: ['foo', 'bar'] },
  { id: 'z', tags: ['baz'] }
];

const filters = ['foo'];

To apply the selected filters to this structure we can

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

// [
//   { id: 'x', tags: ['foo'] },
//   { id: 'y', tags: ['foo', 'bar'] }
// ]
user5470921
  • 576
  • 1
  • 6
  • 16
6

A short way of writing this: const found = arr1.some(arr2.includes)

Vasia Zaretskyi
  • 349
  • 3
  • 9
5

Array .filter() with a nested call to .find() will return all elements in the first array that are members of the second array. Check the length of the returned array to determine if any of the second array were in the first array.

getCommonItems(firstArray, secondArray) {
  return firstArray.filter((firstArrayItem) => {
    return secondArray.find((secondArrayItem) => {
      return firstArrayItem === secondArrayItem;
    });
  });
}
Neoheurist
  • 3,183
  • 6
  • 37
  • 55
  • Is there a way to "clean" the array? Like deleting the values in the second array if they exist in the first? – sandrooco Mar 10 '17 at 15:18
5

Good perfomance solution:

We should transform one of arrays to object.

const contains = (arr1, mainObj) => arr1.some(el => el in mainObj);
const includes = (arr1, mainObj) => arr1.every(el => el in mainObj);

Usage:

const mainList = ["apple", "banana", "orange"];
// We make object from array, you can use your solution to make it
const main = Object.fromEntries(mainList.map(key => [key, true]));

contains(["apple","grape"], main) // => true
contains(["apple","banana","pineapple"], main) // =>  true
contains(["grape", "pineapple"], main) // =>  false

includes(["apple", "grape"], main) // => false
includes(["banana", "apple"], main) // =>  true

you can face with some disadvantage of checking by in operator (eg 'toString' in {} // => true), so you can change solution to obj[key] checker

zemil
  • 3,235
  • 2
  • 24
  • 33
4

Adding to Array Prototype

Disclaimer: Many would strongly advise against this. The only time it'd really be a problem was if a library added a prototype function with the same name (that behaved differently) or something like that.

Code:

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

Without using big arrow functions:

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

Usage

var a = ["a","b"]

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

console.log(a.containsAny(["z"]))    // Outputs false
Community
  • 1
  • 1
csga5000
  • 4,062
  • 4
  • 39
  • 52
4

My solution applies Array.prototype.some() and Array.prototype.includes() array helpers which do their job pretty efficient as well

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;
Emobe
  • 660
  • 11
  • 32
4

When I looked at your answers, I could not find the answer I wanted. I did something myself and I want to share this with you.

It will be true only if the words entered (array) are correct.

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
3

It can be done by simply iterating across the main array and check whether other array contains any of the target element or not.

Try this:

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

Ritesh Kumar Gupta
  • 5,055
  • 7
  • 45
  • 71
3

Not sure how efficient this might be in terms of performance, but this is what I use using array destructuring to keep everything nice and short:

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

Since sets cannot have duplicate elements while arrays can, combining both input arrays, converting it to a set, and comparing the set size and array length would tell you if they share any elements.

Luke Redmore
  • 449
  • 3
  • 10
2

With 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
fguillen
  • 36,125
  • 23
  • 149
  • 210
  • 2
    Personally, although I like underscorejs, this is a classic example of how convoluted code can look. Not only is it hard to comprehend as underscorejs code, but from a general coding point of view, the same is also true (e.g. the word "every" doesn't spring to mind when I want to find index of something in an array but "indexOf" does). We should avoid the needless use of third party tools when for a few characters extra, a pure JavaScript solution could be provided. Using underscorejs for the sake of it means your solution becomes tightly coupled with third party code. – csharpforevermore May 28 '15 at 15:17
  • @csharpforevermore I suppose this is a matter of taste, you say this solution is more _convoluted_ than all of the others using `indexOf` I think the opposite :). In the other hand I agree in trying to not add external libraries if they are not really needed, but I'm not really obsessive with that, third-part libraries not only offer useful functionalities but also _solid_ functionalities. For example: have you tested all the edge-cases and mayor-browsers with your solution?.. (by the way, `every` is not trying to find an index in a list but evaluating something in _every_ element in the list) – fguillen May 29 '15 at 08:12
2

Vanilla JS with partial matching & case insensitive

The problem with some previous approaches is that they require an exact match of every word. But, What if you want to provide results for partial matches?

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

This is useful when you want to provide a search box where users type words and the results can have those words in any order, position and case.

SntsDev
  • 71
  • 2
2

Update @Paul Grimshaw answer, use includes insteed of indexOf for more readable

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

Đinh Anh Huy
  • 505
  • 4
  • 17
1

I came up with a solution in node using underscore js like this:

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

You are looking for intersection between the two arrays. And you have two major intersection types: 'every' and 'some'. Let me give you good examples:

EVERY

let brands1 = ['Ford', 'Kia', 'VW', 'Audi'];
let brands2 = ['Audi', 'Kia'];
// Find 'every' brand intersection. 
// Meaning all elements inside 'brands2' must be present in 'brands1':
let intersectionEvery = brands2.every( brand => brands1.includes(brand) );
if (intersectionEvery) {
    const differenceList = brands1.filter(brand => !brands2.includes(brand));
    console.log('difference list:', differenceList);
    const commonList = brands1.filter(brand => brands2.includes(brand));
    console.log('common list:', commonList);
}

If condition is not met (like if you put 'Mercedes' in brands2) then 'intersectionEvery' won't be satisfied - will be bool false.

If condition is met it will log ["Ford", "VW"] as difference and ["Kia", "Audi"] as common list.

Sandbox: https://jsfiddle.net/bqmg14t6/

SOME

let brands1 = ['Ford', 'Kia', 'VW', 'Audi'];
let brands2 = ['Audi', 'Kia', 'Mercedes', 'Land Rover'];
// Find 'some' brand intersection. 
// Meaning some elements inside 'brands2' must be also present in 'brands1':
let intersectionSome = brands2.some( brand => brands1.includes(brand) );
if (intersectionSome) {
    const differenceList = brands1.filter(brand => !brands2.includes(brand));
    console.log('difference list:', differenceList);
    const commonList = brands1.filter(brand => brands2.includes(brand));
    console.log('common list:', commonList);
}

Here we are looking for some common brands, not necessarily all.

It will log ["Ford", "VW"] as difference and ["Kia", "Audi"] as common brands.

Sandbox: https://jsfiddle.net/zkq9j3Lh/

Vlado
  • 3,517
  • 2
  • 26
  • 24
0

Personally, I would use the following function:

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

The "toString()" method will always use commas to separate the values. Will only really work with primitive types.

csharpforevermore
  • 1,472
  • 15
  • 27
  • 2
    This won't work when the elements are at the beginning or at the end of the array, or in a different order. – DanielM Aug 10 '15 at 08:06
  • 1
    -1 because as DanielM said this is broken. You *could* prepend and append a comma to arrayAsString as a workaround, but honestly it just seems like an overly complicated solution to use strings. – JHH Jan 22 '16 at 08:38
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);
Naveen Koti
  • 96
  • 1
  • 6
0
var target = ["apple","banana","orange"];
var checkArray = ["apple","banana","pineapple"];

var containsOneCommonItem = target.some(x => checkArray.some(y => y === x));`

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

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

["grape", "pineapple"] //returns false;
Vasudev
  • 19
  • 2
-2

you can do something like this

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