web-dev-qa-db-fra.com

Vérifier si un tableau contient un élément d'un autre tableau en JavaScript

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?

212
Alex

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.

247
Paul Grimshaw

Vanille 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;
    });
};
209
skyisred

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.

64
willz

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

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.

40
Ian

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

31
lusk

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.

26
Justin Cuaresma

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

26
Vadim Gremyachev

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!

7
kashpatel

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.

5
Tanvir Hasan

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

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

3
It's me ... Alex

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();
}
2
charles

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

2
Đinh Anh Huy

Ajout au prototype de tableau

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.

Code:

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

Usage

var a = ["a","b"]

console.log(a.containsAny(["b","z"]))    // Outputs true

console.log(a.containsAny(["z"]))    // Outputs false
2
csga5000

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

DEMO chez JSFIDDLE

2
ritesh_NITW

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
2
fguillen

Vanilla JS avec correspondance partielle et insensible à la casse

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.

2
SntsDev

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'] }
// ]
2
user5470921

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;

2

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)
1
Cong Nguyen
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);
0
Naveen Koti
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;
0
Vasudev

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.

0

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;
    });
  });
}
0
Neoheurist