Проверка наличия элементов одного массива в другом массиве на JavaScript
У меня есть целевой массив ["apple","banana","orange"]
, и я хочу проверить, содержатся ли какие-либо элементы этого целевого массива в других массивах.
Например:
["apple","grape"] // возвращает true;
["apple","banana","pineapple"] // возвращает true;
["grape", "pineapple"] // возвращает false;
Как я могу это сделать на JavaScript?
5 ответ(ов)
Ваш код функции 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));
Вот перевод вашего кода на русский язык с объяснением, как это можно использовать в контексте вопроса на 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!
Надеюсь, это поможет!
Если вы не против использовать библиотеку, на сайте 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 возвращает новый массив с совпадениями, а если совпадений нет, он возвращает пустой массив.
Чтобы проверить, содержит ли один массив любые элементы другого массива, вы можете использовать несколько различных подходов в 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.
Рекомендуется использовать метод, который наиболее соответствует вашим потребностям: простота и читабельность против производительности, особенно при работе с большими массивами.
Если вам не нужно преобразование типов (из-за использования 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/
Недостатком этого решения является то, что только числа и строки (и булевы значения) могут использоваться (корректно), поскольку значения (неявно) приводятся к строкам и устанавливаются в качестве ключей к мапе поиска. Это не совсем хорошо/возможно/легко сделать для не-литеральных значений.
Как перемешать (сделать случайным) массив в JavaScript?
Как объединить два массива в JavaScript и удалить дубликаты?
Как очистить массив в JavaScript?
Как получить доступ к вложенным объектам, массивам или JSON и обработать их?
Как удалить все дубликаты из массива объектов?