J'ai un tableau cible ["Apple","banana","orange"]
et je veux vérifier si d'autres tableaux contiennent l'un des éléments du tableau cible.
Par exemple:
["Apple","grape"] //returns true;
["Apple","banana","pineapple"] //returns true;
["grape", "pineapple"] //returns false;
Comment puis-je le faire en JavaScript?
Vanilla JS
ES2016:
const found = arr1.some(r=> arr2.includes(r))
ES6:
const found = arr1.some(r=> arr2.indexOf(r) >= 0)
Comment ça marche
some(..)
vérifie chaque élément du tableau par rapport à une fonction de test et renvoie true si un élément du tableau réussit la fonction de test, sinon il renvoie false. indexOf(..) >= 0
et includes(..)
les deux renvoient vrai si l'argument donné est présent dans le tableau.
/**
* @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;
});
};
Si vous n'êtes pas opposé à l'utilisation d'un libray, http://underscorejs.org/ a une méthode d'intersection, ce qui peut simplifier ceci:
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]
La fonction intersection retournera un nouveau tableau avec les éléments correspondants et, si elle ne correspond pas, elle retournera un tableau vide.
Si vous n'avez pas besoin de coercition de type (à cause de l'utilisation de indexOf
), vous pouvez essayer quelque chose comme:
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);
Où arr
contient les éléments cibles. À la fin, found
indiquera si le second tableau avait au moins un match par rapport à la cible.
Bien sûr, vous pouvez échanger des nombres contre tout ce que vous voulez utiliser - les chaînes conviennent, comme dans votre exemple.
Et dans mon exemple spécifique, le résultat devrait être true
car le 3
du second tableau existe dans la cible.
METTRE À JOUR:
Voici comment je l'organiser dans une fonction (avec quelques modifications mineures d'avant):
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/
Dans ce cas, la fonction peut être modifiée pour que targetArray
soit transmis en tant qu'argument au lieu d'être codé en dur dans la fermeture.
UPDATE2:
Bien que ma solution ci-dessus puisse fonctionner et soit (espérons-le plus) lisible, je pense que la "meilleure" façon de gérer le concept que j'ai décrit est de faire les choses un peu différemment. Le "problème" avec la solution ci-dessus est que la variable indexOf
à l'intérieur de la boucle fait boucler complètement le tableau cible pour chaque élément de l'autre tableau. Cela peut facilement être "corrigé" en utilisant une "recherche" (une carte ... un littéral d'objet JavaScript). Cela permet deux boucles simples, sur chaque tableau. Voici un exemple:
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/
L'inconvénient de cette solution est que seuls les nombres et les chaînes (et les booléens) peuvent être utilisés (correctement), car les valeurs sont (implicitement) converties en chaînes et définies comme clés de la mappe de recherche. Ce n'est pas exactement bon/possible/facile à faire pour des valeurs non littérales.
ES6 (le plus rapide)
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));
Souligner
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
Vous pouvez utiliser lodash et faire:
_.intersection(originalTarget, arrayToCheck).length > 0
L'intersection des ensembles est effectuée sur les deux collections, produisant un tableau d'éléments identiques.
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"]));
J'ai trouvé cette syntaxe courte et douce pour correspondre à tout ou partie des éléments entre deux tableaux. Par exemple
// opération OR. trouve si l'un des éléments de array2 existe dans array1. Ceci retournera dès qu'il y aura une première correspondance quand une méthode sera cassée quand la fonction retournera TRUE
let array1 = ['a', 'b', 'c', 'd', 'e'], array2 = ['a', 'b'];
console.log(array2.some(ele => array1.includes(ele)));
// affiche VRAI
// opération AND. trouve si tous les éléments de array2 existent dans array1. Cela retournera dès qu'il n'y aura pas de première correspondance car une méthode s'interrompra lorsque la fonction retournera TRUE
let array1 = ['a', 'b', 'c', 'd', 'e'], array2 = ['a', 'x'];
console.log(!array2.some(ele => !array1.includes(ele)));
// affiche FAUX
J'espère que cela aidera quelqu'un à l'avenir!
Solution ES6:
let arr1 = [1, 2, 3];
let arr2 = [2, 3];
let isFounded = arr1.some( ai => arr2.includes(ai) );
Contrairement à cela: Doit contenir toutes les valeurs.
let allFounded = arr2.every( ai => arr1.includes(ai) );
Espoir, sera utile.
Vous pouvez utiliser un appel imbriqué Array.prototype.some. Cela a l’avantage qu’elle résoudra au premier match au lieu d’autres solutions qui passeront par la boucle imbriquée.
par exemple.
var arr = [1, 2, 3];
var match = [2, 4];
var hasMatch = arr.some(a => match.some(m => a === m));
Pourquoi ne pas utiliser une combinaison de some/findIndex et indexOf?
Donc, quelque chose comme ça:
var array1 = ["Apple","banana","orange"];
var array2 = ["grape", "pineapple"];
var found = array1.some(function(v) { return array2.indexOf(v) != -1; });
Pour le rendre plus lisible, vous pouvez ajouter cette fonctionnalité à l'objet Array lui-même.
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;
}
Remarque: Si vous voulez utiliser quelque chose avec un prédicat, vous pouvez remplacer l'index interneOf par un autre findIndex et un prédicat
Je suis venu avec une solution dans le noeud en utilisant soulignement js comme ceci:
var checkRole = _.intersection(['A','B'], ['A','B','C']);
if(!_.isEmpty(checkRole)) {
next();
}
Mise à jour de la réponse de @Paul Grimshaw, utilisez includes
au lieu de indexOf
pour plus de lisibilité
laisser trouvé = arr1.some (r => arr2.includes (r))
Avertissement: Beaucoup déconseilleraient fortement cela. La seule fois où il y aurait vraiment un problème était si une bibliothèque ajoutait une fonction prototype avec le même nom (qui se comportait différemment) ou quelque chose comme ça.
Array.prototype.containsAny = function(arr) {
return this.some(
(v) => (arr.indexOf(v) >= 0)
)
}
Sans utiliser les grandes fonctions de flèche:
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
Cela peut être fait en parcourant simplement le tableau principal et en vérifiant si un autre tableau contient ou non l'un des éléments cibles.
Essaye ça:
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));
Avec 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
Le problème avec certaines approches précédentes est qu’elles requièrent une correspondance exacte de chaque mot. Mais, Et si vous voulez fournir des résultats pour des correspondances partielles?
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"]
Cela est utile lorsque vous souhaitez fournir un champ de recherche dans lequel les utilisateurs tapent des mots et les résultats peuvent avoir ces mots dans n'importe quel ordre, position et casse.
Voici un cas intéressant que je pensais devoir partager.
Disons que vous avez un tableau d'objets et un tableau de filtres sélectionnés.
let arr = [
{ id: 'x', tags: ['foo'] },
{ id: 'y', tags: ['foo', 'bar'] },
{ id: 'z', tags: ['baz'] }
];
const filters = ['foo'];
Pour appliquer les filtres sélectionnés à cette structure, nous pouvons
if (filters.length > 0)
arr = arr.filter(obj =>
obj.tags.some(tag => filters.includes(tag))
);
// [
// { id: 'x', tags: ['foo'] },
// { id: 'y', tags: ['foo', 'bar'] }
// ]
Ma solution s'applique Array.prototype.some () et Array.prototype.includes () array helpers, qui font également très bien leur travail.
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;
Juste une solution de plus
var a1 = [1, 2, 3, 4, 5]
var a2 = [2, 4]
Vérifier si a1 contient tous les éléments de a2
var result = a1.filter(e => a2.indexOf(e) !== -1).length === a2.length
console.log(result)
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);
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;
Personnellement, j'utiliserais la fonction suivante:
var arrayContains = function(array, toMatch) {
var arrayAsString = array.toString();
return (arrayAsString.indexOf(','+toMatch+',') >-1);
}
La méthode "toString ()" utilisera toujours des virgules pour séparer les valeurs. Ne fonctionnera vraiment qu'avec des types primitifs.
Array .filter () avec un appel imbriqué à .find () renverra tous les éléments du premier tableau membres du second tableau. Vérifiez la longueur du tableau retourné pour déterminer si l'un des deux tableaux se trouvait dans le premier tableau.
getCommonItems(firstArray, secondArray) {
return firstArray.filter((firstArrayItem) => {
return secondArray.find((secondArrayItem) => {
return firstArrayItem === secondArrayItem;
});
});
}