183 votes

Comment savoir si deux tableaux ont les mêmes valeurs ?

J'ai deux tableaux : l'un est rempli avec des informations provenant d'une requête ajax et l'autre stocke les boutons sur lesquels l'utilisateur clique. J'utilise ce code (que j'ai rempli avec des exemples de chiffres) :

var array1 = [2, 4];
var array2 = [4, 2]; //It cames from the user button clicks, so it might be disordered.
array1.sort(); //Sorts both Ajax and user info.
array2.sort();
if (array1==array2) {
    doSomething();
}else{
    doAnotherThing();
}

Mais il donne toujours false même si les deux tableaux sont identiques, mais portent des noms différents. (J'ai vérifié cela dans la console JS de Chrome). Alors, y a-t-il un moyen de savoir si ces deux tableaux contiennent la même chose ? Pourquoi cela donne-t-il false ? Comment puis-je savoir quelles valeurs du premier tableau ne sont pas dans le second ?

148voto

kennebec Points 33886

Si les éléments de votre tableau ne sont pas des objets - s'il s'agit de nombres ou de chaînes, par exemple, vous pouvez comparer leurs chaînes jointes pour voir s'ils ont les mêmes membres dans n'importe quel ordre -.

var array1= [10, 6, 19, 16, 14, 15, 2, 9, 5, 3, 4, 13, 8, 7, 1, 12, 18, 11, 20, 17];
var array2= [12, 18, 20, 11, 19, 14, 6, 7, 8, 16, 9, 3, 1, 13, 5, 4, 15, 10, 2, 17];

if(array1.sort().join(',')=== array2.sort().join(',')){
    alert('same members');
}
else alert('not a match');

65voto

Technotronic Points 148

Si vous souhaitez vérifier uniquement si deux tableaux ont les mêmes valeurs (indépendamment du nombre d'occurrences et de l'ordre de chaque valeur), vous pouvez le faire en utilisant lodash :

_.isEmpty(_.xor(array1, array2))

Court, simple et joli !

59voto

Maciej Krawczyk Points 4533

Triez les tableaux et comparez leurs valeurs une à une.

function arrayCompare(_arr1, _arr2) {
    if (
      !Array.isArray(_arr1)
      || !Array.isArray(_arr2)
      || _arr1.length !== _arr2.length
      ) {
        return false;
      }

    // .concat() to not mutate arguments
    const arr1 = _arr1.concat().sort();
    const arr2 = _arr2.concat().sort();

    for (let i = 0; i < arr1.length; i++) {
        if (arr1[i] !== arr2[i]) {
            return false;
         }
    }

    return true;
}

47voto

mheiber Points 290

Pourquoi votre code n'a pas fonctionné

En JavaScript, pour les types de données non primitifs tels que les tableaux, == y === vérifie l'égalité des références (en laissant de côté les conversions de type qui == peut effectuer). En d'autres termes, ils vérifient si arr1 y arr2 sont le même objet en mémoire. Dans votre exemple, les deux tableaux ont les mêmes éléments dans le même ordre, mais ne sont pas égaux.

Voici un exemple qui, je l'espère, renforcera l'intuition selon laquelle false est le bon résultat pour [1] === [1] :

const x = [1];
const y = [1];
x === y; // false
x[0] = 200;
console.log(x); // "Array [ 200 ]"
console.log(y); // "Array [ 1 ]"
x === y; // false

Solutions

Deux tableaux, arr1 y arr2 ont les mêmes membres si et seulement si :

  • Tout dans arr2 está en arr1

ET

  • Tout dans arr1 está en arr2

Ceci fera donc l'affaire (ES2016) :

const containsAll = (arr1, arr2) => 
                arr2.every(arr2Item => arr1.includes(arr2Item))

const sameMembers = (arr1, arr2) => 
                        containsAll(arr1, arr2) && containsAll(arr2, arr1);

sameMembers(arr1, arr2); // `true`

Cette deuxième solution utilisant Underscore est plus proche de ce que vous essayez de faire :

arr1.sort();
arr2.sort();

_.isEqual(arr1, arr2); // `true`

Il fonctionne parce que isEqual vérifie l'"égalité profonde", ce qui signifie qu'il ne se limite pas à l'égalité des références et qu'il compare les valeurs.

Une solution à votre troisième question

Vous avez également demandé comment savoir quels éléments de la arr1 ne sont pas contenues dans arr2 .

Ceci fera l'affaire (ES2015) :

const arr1 = [1, 2, 3, 4];
const arr2 = [3, 2, 1];

arr1.filter(arr1Item => !arr2.includes(arr1Item)); // `[4]`

Vous pouvez également utiliser la fonction difference : méthode :

_.difference(arr1, arr2); // `[4]`

MISE À JOUR

Voir le commentaire de @Redu - ma solution est la suivante sameMembers mais ce que vous avez peut-être à l'esprit, c'est sameMembersInOrder également connu sous le nom de deepEquals .

MISE À JOUR 2

Si vous ne vous souciez pas de l'ordre des membres des tableaux, la fonction Set peut être une meilleure structure de données que Array . Voir le Notes du MDN sur la mise en œuvre isSuperset y difference en utilisant le dangereux monkey-Parcheando.

Mise à jour 3

Si l'ordre n'a pas d'importance, il est toujours préférable d'utiliser des ensembles. Mais si vous devez utiliser des tableaux, cette solution a une meilleure complexité temporelle que celle que j'ai donnée précédemment :

function sameMembers(arr1, arr2) {
    const set1 = new Set(arr1);
    const set2 = new Set(arr2);
    return arr1.every(item => set2.has(item)) &&
        arr2.every(item => set1.has(item))
}

43voto

isakkarlsson Points 551
Array.prototype.compare = function(testArr) {
    if (this.length != testArr.length) return false;
    for (var i = 0; i < testArr.length; i++) {
        if (this[i].compare) { //To test values in nested arrays
            if (!this[i].compare(testArr[i])) return false;
        }
        else if (this[i] !== testArr[i]) return false;
    }
    return true;
}

var array1 = [2, 4];
var array2 = [4, 2];
if(array1.sort().compare(array2.sort())) {
    doSomething();
} else {
    doAnotherThing();
}

Peut-être ?

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X