Check if an array contains any element of another array in JavaScript

后端 未结 26 1095
礼貌的吻别
礼貌的吻别 2020-11-22 08:48

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:

相关标签:
26条回答
  • 2020-11-22 08:56

    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'] }
    // ]
    
    0 讨论(0)
  • 2020-11-22 08:57

    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.

    0 讨论(0)
  • 2020-11-22 08:58

    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;
        });
    };
    
    0 讨论(0)
  • 2020-11-22 08:59

    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
    
    0 讨论(0)
  • 2020-11-22 08:59

    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.

    0 讨论(0)
  • 2020-11-22 09:01

    You could use lodash and do:

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

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

    0 讨论(0)
提交回复
热议问题