9

Проверка наличия элементов одного массива в другом массиве на JavaScript

3

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

Например:

["apple","grape"] // возвращает true;

["apple","banana","pineapple"] // возвращает true;

["grape", "pineapple"] // возвращает false;

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

5 ответ(ов)

3

Ваш код функции findOne определяет, содержит ли массив haystack хотя бы один элемент из другого массива arr. Вот как это выглядит в Vanilla JS:

/**
 * @description Определяет, содержит ли массив хотя бы один элемент из другого массива.
 * @param {array} haystack Массив, в котором производится поиск.
 * @param {array} arr Массив, содержащий элементы, которые нужно найти в haystack.
 * @return {boolean} true|false, если haystack содержит хотя бы один элемент из arr.
 */
var findOne = function (haystack, arr) {
    return arr.some(function (v) {
        return haystack.indexOf(v) >= 0;
    });
};

Как отметил @loganfsmyth, в ES2016 этот код можно сократить:

/**
 * @description Определяет, содержит ли массив хотя бы один элемент из другого массива.
 * @param {array} haystack Массив, в котором производится поиск.
 * @param {array} arr Массив, содержащий элементы, которые нужно найти в haystack.
 * @return {boolean} true|false, если haystack содержит хотя бы один элемент из arr.
 */
const findOne = (haystack, arr) => {
    return arr.some(v => haystack.includes(v));
};

Или даже проще, просто так: arr.some(v => haystack.includes(v));.

Если вам нужно определить, содержит ли массив все элементы из другого массива, замените some() на every():

arr.every(v => haystack.includes(v));
1

Вот перевод вашего кода на русский язык с объяснением, как это можно использовать в контексте вопроса на StackOverflow:


Вопрос: Как проверить, содержатся ли некоторые элементы одного массива в другом массиве в ES6?

Ответ:

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

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

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

В этом коде isFound будет true, если хотя бы один элемент из arr1 найден в arr2.

Если вам нужно проверить, содержатся ли все элементы одного массива в другом массиве, вы можете использовать метод every следующим образом:

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

В данном случае allFound будет true, только если каждый элемент из arr2 присутствует в arr1.

Таким образом, вы можете легко осуществлять такие проверки с помощью методов массива в ES6!


Надеюсь, это поможет!

0

Если вы не против использовать библиотеку, на сайте http://underscorejs.org есть метод intersection, который может упростить вашу задачу:

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)); // возвращает ['apple', 'orange']
console.log(_.intersection(target, fruit3)); // возвращает []
console.log(_.intersection(target, fruit4)); // возвращает ['orange']

Метод intersection возвращает новый массив с совпадениями, а если совпадений нет, он возвращает пустой массив.

0

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

ES6 (самый быстрый способ):

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

В этом подходе мы используем метод some(), который проверяет, есть ли в массиве a хотя бы один элемент, который также содержится в массиве b. Мы ищем элемент с помощью метода indexOf(), который возвращает индекс, начиная с которого мы можем проверить, присутствует ли элемент. Если элемент найден, indexOf() вернет его индекс, и условие (!== -1) станет истинным.

ES2016:

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

Этот вариант использует метод includes(), который более читабелен, но может быть немного медленнее по производительности по сравнению с предыдущим методом indexOf().

Underscore:

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

Если вы используете библиотеку Underscore.js, вы можете воспользоваться методом intersection(), который возвращает массив элементов, присутствующих в обоих массивах. Здесь мы проверяем, есть ли в результате пересечения хотя бы один элемент, смотря на длину возвращаемого массива.

Демо и производительность:

Вы можете протестировать разные подходы, чтобы увидеть, какой из них работает быстрее, по следующей ссылке: DEMO на jsfiddle. Также есть тест на производительность с помощью jsPerf: jsPerf.

Рекомендуется использовать метод, который наиболее соответствует вашим потребностям: простота и читабельность против производительности, особенно при работе с большими массивами.

0

Если вам не нужно преобразование типов (из-за использования 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;
}());

ДЕМО: http://jsfiddle.net/u8Bzt/

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


ОБНОВЛЕНИЕ2:

Хотя мое решение выше может работать и (надеюсь, более) читабельно, я считаю, что "лучше" подходить к описанной концепции немного иначе. "Проблема" с вышеуказанным решением в том, что indexOf внутри цикла заставляет целевой массив полностью обходится для каждого элемента другого массива. Это можно легко "исправить", используя "поиск" (мап... литерал объекта JavaScript). Это позволяет использовать два простых цикла, по каждому массиву. Вот пример:

var anyMatchInArray = function (target, toMatch) {
    "use strict";

    var found, targetMap, i, j, cur;

    found = false;
    targetMap = {};

    // Сохраняем все значения из массива `target` в мапе,
    // где ключи - это значения из массива
    for (i = 0, j = target.length; i < j; i++) {
        cur = target[i];
        targetMap[cur] = true;
    }

    // Цикл по всем элементам массива `toMatch` и проверяем, 
    // есть ли их значения в мапе из предыдущего шага
    for (i = 0, j = toMatch.length; !found && (i < j); i++) {
        cur = toMatch[i];
        found = !!targetMap[cur];
        // Если найдено, `targetMap[cur]` вернет true, иначе
        // это будет `undefined`...вот для чего используется `!!`
    }

    return found;
};

ДЕМО: http://jsfiddle.net/5Lv9v/

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

Чтобы ответить на вопрос, пожалуйста, войдите или зарегистрируйтесь