web-dev-qa-db-fra.com

Comment savoir si deux tableaux ont les mêmes valeurs

J'ai ces deux tableaux: l'un contient les informations d'une demande ajax et l'autre stocke les boutons sur lesquels l'utilisateur clique. J'utilise ce code (j'ai rempli avec des numéros d'échantillon):

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 cela donne toujours false, même si les deux tableaux sont identiques, mais avec un nom différent. (J'ai vérifié cela dans la console JS de Chrome). Alors, y a-t-il moyen de savoir si ces deux tableaux contiennent le même? Pourquoi donne-t-il false? Comment puis-je savoir quelles valeurs dans le premier tableau ne sont pas dans le second?

76
Carlos Precioso
function arraysEqual(_arr1, _arr2) {

    if (!Array.isArray(_arr1) || ! Array.isArray(_arr2) || _arr1.length !== _arr2.length)
      return false;

    var arr1 = _arr1.concat().sort();
    var arr2 = _arr2.concat().sort();

    for (var i = 0; i < arr1.length; i++) {

        if (arr1[i] !== arr2[i])
            return false;

    }

    return true;

}

Notez que cela ne modifie pas les tableaux d'origine contrairement à une réponse précédente.

12
Maciej Krawczyk

Si vos éléments de tableau ne sont pas des objets, par exemple des nombres ou des chaînes, 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');
70
kennebec
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? 

42
isakkarlsson

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

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

Bref, simple et joli!

37
Technotronic

Pourquoi votre code n'a pas fonctionné

JavaScript a types de données primitifs et types de données non primitifs.

Pour les types de données primitifs, == et === vérifient si les éléments situés de part et d'autre des barres ont la même valeur. C'est pourquoi 1 === 1 est vrai. 

Pour les types de données non primitifs comme les tableaux, == et ===, vérifiez l’égalité des références. C'est-à-dire qu'ils vérifient si arr1 et arr2 sont le même objet. Dans votre exemple, les deux tableaux ont les mêmes objets dans le même ordre, mais ne sont pas équivalents.

Solutions

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

  • Tout dans arr2 est dans arr1

ET

  • Tout dans arr1 est dans arr2

Donc, cela fera 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 seconde solution utilisant Underscore est plus proche de ce que vous tentiez de faire:

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

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

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

Une solution à votre troisième question

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

Cela le fera (ES2015):

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

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

Vous pouvez également utiliser la méthode difference : de Underscore:

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

METTRE À JOUR

Voir le commentaire de @ Redu - ma solution est pour sameMembers, mais vous pouvez avoir en tête sameMembersInOrder, également appelé deepEquals.

MISE À JOUR 2

Si vous ne vous souciez pas de l'ordre des membres des tableaux, les Set d'ES2015 + peuvent être une meilleure structure de données que Array. Voir les remarques MDN sur la façon de mettre en œuvre isSuperset et difference en utilisant un patch de singe dangereux.

23
Max Heiber

Vérification de l'égalité d'objet: JSON.stringify(array1.sort()) === JSON.stringify(array2.sort())

Le test ci-dessus fonctionne également avec des tableaux d'objets, auquel cas une fonction de tri est décrite dans http://www.w3schools.com/jsref/jsref_sort.asp

Cela pourrait suffire pour les petits tableaux contenant des schémas JSON plats.

6
Sandeep

Lorsque vous comparez ces deux tableaux, vous comparez les objets qui représentent les tableaux, pas le contenu. 

Vous devrez utiliser une fonction pour comparer les deux. Vous pouvez écrire votre propre boucle qui en boucle une et la comparer à une autre après avoir vérifié que les longueurs sont les mêmes.

3
Andrew

Notre objectif est essentiellement de vérifier si 2 tableaux sont égaux. Ici, ensemble signifie mathématique set . Le tri le plus rapide prend asymptotiquement O(nlog(n)) temps. Vous pouvez effectuer cette opération de manière asymptotique O(n) avec une structure de données de dictionnaire. En JS, un dictionnaire est simplement un objet avec des clés et des valeurs.

// assumes array elements are primitive types
function areArraysEqualSets(a1, a2) {
  let superSet = {};
  for (let i = 0; i < a1.length; i++) {
    const e = a1[i] + typeof a1[i];
    superSet[e] = 1;
  }

  for (let i = 0; i < a2.length; i++) {
    const e = a2[i] + typeof a2[i];
    if (!superSet[e]) {
      return false;
    }
    superSet[e] = 2;
  }

  for (let e in superSet) {
    if (superSet[e] === 1) {
      return false;
    }
  }

  return true;
}

Notez que cette fonction fonctionne avec des tableaux de types primitifs et suppose que a1 et a2 sont des tableaux

2
canbax

J'ai eu des valeurs entières simples dans un projet de jeu
Avait moins de nombre de valeurs dans chaque tableau, aussi, avait besoin de ce tableau original intacte
Donc, j'ai fait le dessous, ça a bien fonctionné. (Code édité pour coller ici)

var sourceArray = [1, 2, 3];
var targetArray = [3, 2, 1];

if (sourceArray.length !== targetArray.length) {
    // not equal
    // did something
    return false;
}

var newSortedSourceArray = sourceArray.slice().sort();
var newSortedTargetArray = targetArray.slice().sort();

if (newSortedSourceArray.toString() !== newSortedTargetArray.toString()) { // MAIN CHECK
    // not equal
    // did something
    return false;
}
else {
    // equal
    // did something
    // continued further below
}

// did some more work

return true;

J'espère que cela pourra aider.

1

Si vous utilisez le prototype, vous pouvez utiliser la méthode intersect d'un tableau pour déterminer si elles sont identiques (quel que soit leur ordre):

var array1 = [1,2];
var array2 = [2,1];

if(array1.intersect(array2).length === array1.length) {
    alert("arrays are the same!");
}
1
Erfan

Si les éléments du tableau sont des primitives (nombres ou caractères uniques), vous pouvez combiner différentes longueurs et utiliser des ensembles.

function equalArrayItems(arr1, arr2) {
  if (arr1.length !== arr2.length) return false
  const set1 = new Set(arr1)
  const set2 = new Set(arr2)
  const set3 = new Set(arr1, arr2)
  return set1.size === set3.size && set2.size === set3.size
}
0
Stefan Musarra

veuillez vérifier cette réponse

var arr1= [12,18];
var arr2= [12, 18, 20, 11, 19, 14, 6, 7, 8, 16, 9, 3, 1, 13, 5, 4, 15, 10, 2, 17];
for(i=0;i<arr1.length;i++)
{
var array1=arr1[i];
for(j=0;j<arr2.length;j++)
{
    var array2=arr2[j];
    if(array1==array2)
    {
return true;
    }
}
}
0
Vinoth

Utiliser ES6

Nous utiliserons la fonction equals de Ramda, mais nous pourrons utiliser celui de Lodash ou de Underscore isEqual:

const R = require('ramda');

const arraysHaveSameValues = (arr1, arr2) => R.equals( [...arr1].sort(), [...arr2].sort() )

En utilisant l'opporator spread, nous évitons de muter les tableaux originaux et nous gardons notre fonction pure. 

0
Ben Carp