Проверьте, содержит ли массив какой-либо элемент другого массива в JavaScript

У меня есть целевой массив ["apple","banana","orange"], и я хочу проверить, содержат ли другие массивы какие-либо из элементов целевого массива.

Например:

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

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

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

Как я могу сделать это в JavaScript?

Ответ 1

Ваниль JS

ES2016:

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

ES6:

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

Как это устроено

some(..) проверяет каждый элемент массива на соответствие тестовой функции и возвращает true, если какой-либо элемент массива проходит тестовую функцию, в противном случае возвращается false. indexOf(..) >= 0 и includes(..) оба возвращают истину, если данный аргумент присутствует в массиве.

Ответ 2

ваниль 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;
    });
};

Ответ 3

Если вы не против использования 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]

Функция пересечения вернет новый массив с элементами, которые он сопоставил, а если не совпадает с ним, возвращает пустой массив.

Ответ 4

Если вам не требуется принуждение типа (из-за использования 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 существует в целевом объекте.


UPDATE:

Вот как бы я организовал его в функцию (с некоторыми незначительными изменениями ранее):

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 what the `!!` is for
    }

    return found;
};

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

Недостатком этого решения является то, что только числа и строки (и логические значения) могут использоваться (правильно), потому что значения (неявно) преобразуются в строки и задаются в качестве ключей к карте поиска. Это не совсем хорошо/возможно/легко сделано для нелитеративных значений.

Ответ 6

Использование 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"]));

Ответ 7

Вы можете использовать lodash и делать:

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

Установить пересечение выполняется для обеих коллекций, создавая массив одинаковых элементов.

Ответ 8

Я нашел этот короткий и сладкий синтаксис для соответствия всем или некоторым элементам между двумя массивами. Например

//ИЛИ операция. найдите, существует ли какой-либо из элементов array2 в массиве 1. Это вернется, как только будет первое совпадение, когда какой-то метод прерывается, когда функция возвращает TRUE

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

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

//выводит TRUE

//И операция. найти, если все элементы array2 существуют в array1. Это вернется, как только нет первого совпадения, когда какой-то метод прерывается, когда функция возвращает TRUE

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

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

//печатает FALSE

Надеюсь, что это поможет кому-то в будущем!

Ответ 9

Вы можете использовать вложенный вызов Array.prototype.some. Это имеет то преимущество, что оно будет залогом в первом матче вместо других решений, которые будут выполняться через полный вложенный цикл.

например.

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

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

Ответ 10

Как насчет использования комбинации некоторых /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 и предикат

Ответ 11

Мое решение использует помощники массивов Array.prototype.some() и Array.prototype.include(), которые также выполняют свою работу довольно эффективно.

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;

Ответ 12

Это можно сделать, просто выполнив итерацию по основному массиву и проверив, содержит ли другой массив какой-либо из целевого элемента или нет.

Попробуйте следующее:

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 в JSFIDDLE

Ответ 13

С 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

Ответ 14

Добавление в массив прототипов

Отказ от ответственности:. Многие будут категорически против этого. Единственный раз, когда это действительно было проблемой, было то, что библиотека добавила функцию прототипа с тем же именем (которая вела себя по-другому) или что-то в этом роде.

Код:

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

Без использования больших функций стрелок:

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

Ответ 15

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

Ответ 16

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

Это полезно, если вы хотите предоставить окно поиска, в котором пользователи могут вводить слова и результаты, могут иметь эти слова в любом порядке, положении и случае.

Ответ 17

Обновление @Paul Гримшоу ответ, использование includes insteed из indexOf для более читаемым

пусть найдено = arr1.some(r => arr2.indexOf(r)> = 0)
найдем = arr1.some(r => arr2.includes(r))

Ответ 18

Вот интересный случай, я думал, что должен поделиться.

Скажем, у вас есть массив объектов и массив выбранных фильтров.

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

const filters = ['foo'];

Чтобы применить выбранные фильтры к этой структуре, мы можем

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

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

Ответ 19

Я придумал решение в node с помощью подчеркивания js следующим образом:

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

Ответ 20

Решение 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) );

Надеюсь, будет полезно.

Ответ 21

Лично я использовал бы следующую функцию:

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

Метод toString() всегда будет использовать запятые для разделения значений. Будет работать только с примитивными типами.

Ответ 22

Array.filter() с вложенным вызовом .find() вернет все элементы в первом массиве, которые являются членами второго массива. Проверьте длину возвращаемого массива, чтобы определить, был ли какой-либо из второго массива в первом массиве.

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

Ответ 23

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

Ответ 24

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;

Ответ 25

Еще одно решение

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)