Pour comparer des tableaux, il faut les parcourir en boucle et comparer chaque valeur :
Comparaison de tableaux :
// Warn if overriding existing method
if(Array.prototype.equals)
console.warn("Overriding existing Array.prototype.equals. Possible causes: New API defines the method, there's a framework conflict or you've got double inclusions in your code.");
// attach the .equals method to Array's prototype to call it on any array
Array.prototype.equals = function (array) {
// if the other array is a falsy value, return
if (!array)
return false;
// compare lengths - can save a lot of time
if (this.length != array.length)
return false;
for (var i = 0, l=this.length; i < l; i++) {
// Check if we have nested arrays
if (this[i] instanceof Array && array[i] instanceof Array) {
// recurse into the nested arrays
if (!this[i].equals(array[i]))
return false;
}
else if (this[i] != array[i]) {
// Warning - two different object instances will never be equal: {x:20} != {x:20}
return false;
}
}
return true;
}
// Hide method from for-in loops
Object.defineProperty(Array.prototype, "equals", {enumerable: false});
Utilisation :
[1, 2, [3, 4]].equals([1, 2, [3, 2]]) === false;
[1, "2,3"].equals([1, 2, 3]) === false;
[1, 2, [3, 4]].equals([1, 2, [3, 4]]) === true;
[1, 2, 1, 2].equals([1, 2, 1, 2]) === true;
Vous pouvez dire " Mais il est beaucoup plus rapide de comparer des chaînes de caractères - sans boucles... "Eh bien, vous devriez noter qu'il y a des boucles. La première boucle récursive qui convertit le tableau en chaîne de caractères et la seconde, qui compare deux chaînes de caractères. Donc cette méthode est plus rapide que l'utilisation de la chaîne de caractères .
Je pense que les grandes quantités de données devraient toujours être stockées dans des tableaux, et non dans des objets. Cependant, si vous utilisez des objets, ils peuvent aussi être partiellement comparés.<br><strong>Voici comment :</strong>
Comparer des objets :
J'ai dit plus haut, que deux objets instances ne seront jamais égales, même si elles contiennent les mêmes données à ce moment-là :
({a:1, foo:"bar", numberOfTheBeast: 666}) == ({a:1, foo:"bar", numberOfTheBeast: 666}) //false
Cela a une raison, car il peut y avoir, par exemple les variables privées dans les objets.
Toutefois, si vous utilisez uniquement la structure d'objet pour contenir les données, la comparaison est toujours possible :
Object.prototype.equals = function(object2) {
//For the first loop, we only check for types
for (propName in this) {
//Check for inherited methods and properties - like .equals itself
//https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/hasOwnProperty
//Return false if the return value is different
if (this.hasOwnProperty(propName) != object2.hasOwnProperty(propName)) {
return false;
}
//Check instance type
else if (typeof this[propName] != typeof object2[propName]) {
//Different types => not equal
return false;
}
}
//Now a deeper check using other objects property names
for(propName in object2) {
//We must check instances anyway, there may be a property that only exists in object2
//I wonder, if remembering the checked values from the first loop would be faster or not
if (this.hasOwnProperty(propName) != object2.hasOwnProperty(propName)) {
return false;
}
else if (typeof this[propName] != typeof object2[propName]) {
return false;
}
//If the property is inherited, do not check any more (it must be equa if both objects inherit it)
if(!this.hasOwnProperty(propName))
continue;
//Now the detail check and recursion
//This returns the script back to the array comparing
/**REQUIRES Array.equals**/
if (this[propName] instanceof Array && object2[propName] instanceof Array) {
// recurse into the nested arrays
if (!this[propName].equals(object2[propName]))
return false;
}
else if (this[propName] instanceof Object && object2[propName] instanceof Object) {
// recurse into another objects
//console.log("Recursing to compare ", this[propName],"with",object2[propName], " both named \""+propName+"\"");
if (!this[propName].equals(object2[propName]))
return false;
}
//Normal value comparison for strings and numbers
else if(this[propName] != object2[propName]) {
return false;
}
}
//If everything passed, let's say YES
return true;
}
Toutefois, n'oubliez pas que celle-ci doit servir à comparer des données de type JSON, et non des instances de classe ou d'autres éléments. Si vous voulez comparer des objets plus compliqués, regardez à cette réponse et sa fonction superlongue .
Pour que cela fonctionne avec Array.equals
vous devez modifier un peu la fonction originale :
...
// Check if we have nested arrays
if (this[i] instanceof Array && array[i] instanceof Array) {
// recurse into the nested arrays
if (!this[i].equals(array[i]))
return false;
}
/**REQUIRES OBJECT COMPARE**/
else if (this[i] instanceof Object && array[i] instanceof Object) {
// recurse into another objects
//console.log("Recursing to compare ", this[propName],"with",object2[propName], " both named \""+propName+"\"");
if (!this[i].equals(array[i]))
return false;
}
else if (this[i] != array[i]) {
...
J'ai fait un petit outil de test pour les deux fonctions .
Bonus : tableaux imbriqués avec indexOf
y contains
Samy Bencherif a préparé des fonctions utiles dans le cas où vous recherchez un objet spécifique dans des tableaux imbriqués, qui sont disponibles ici : https://jsfiddle.net/SamyBencherif/8352y6yw/
6 votes
Vous pourriez d'abord comparer leur longueur, et si elles sont égales, chaque valeur.
63 votes
Qu'est-ce qui rend deux tableaux égaux pour vous ? Les mêmes éléments ? Le même ordre des éléments ? L'encodage en JSON ne fonctionne que si l'élément du tableau peut être sérialisé en JSON. Si le tableau peut contenir des objets, jusqu'où pouvez-vous aller ? Quand deux objets sont-ils "égaux" ?
0 votes
JSON.parse
itérerait également à travers chaque valeur de toute façon, donc je suppose qu'il serait mieux de comparer l'itération à travers chaque valeur et de réduire certaines étapes d'exécution (comme l'encodage en JSON).1 votes
Duplicata possible stackoverflow.com/questions/27030/
0 votes
@Blender - peut-être, mais les exemples que j'ai trouvés sur SO ne concernaient que des cas spécifiques. faire quelque chose avec les tableaux, comme sortir tous les éléments présents dans l'un mais pas dans l'autre, ce qui impliquerait d'itérer à travers chaque élément. Felix, dans ce cas, les mêmes éléments dans le même ordre.
64 votes
@FelixKling, la définition de l'"égalité" est certainement un sujet subtil, mais pour les personnes qui arrivent à JavaScript à partir de langages de plus haut niveau, il n'y a pas d'excuse pour des idioties telles que
([] == []) == false
.0 votes
Duplicata possible de Comment vérifier un tableau identique de la manière la plus efficace ?
6 votes
@AlexD il semble que les tableaux utilisent l'égalité des références, ce qui est ce que l'on attend. Ce serait assez terrible si vous ne pouviez pas le faire.
5 votes
@AlexD Je ne peux pas penser à une langue où cela ne se produit pas. En C++, vous comparez deux pointeurs - faux. En Java, vous faites la même chose qu'en javascript. En PHP, quelque chose dans les coulisses bouclera les tableaux - appelez-vous PHP un langage de niveau supérieur ?
0 votes
[2, 1].toSTring() == [2, 1].toString()
0 votes
[1, 2].join() === [1, 2].join()
2 votes
Je dis que si vous ne travaillez pas avec d'ÉNORMES ensembles de données où vous seriez en mesure de mesurer une réduction de vitesse de 1s ou plus, restez avec ce que vous faites maintenant. Comme je ne fais rien de critique avec JS, je me contente généralement de cela :
if (a1.length!==a2.length || JSON.stringify(a1)!==JSON.stringify(a2)) { /* something is different */ }
1 votes
@TomášZato-ReinstateMonica Je suis presque d'accord, sauf qu'il y a deux opérateurs d'égalité différents en js. En Python, vous avez
is
y==
L'un vérifie l'égalité des références, et l'autre utilise une comparaison intégrée ou surchargée. À mon avis, c'est beaucoup plus intuitif et utile que l'état actuel des choses.1 votes
Une fois que le proposition d'enregistrements et de tuples est accepté, vous pouvez comparer des tuples à la place :
#[1, 2, 3] === #[1, 2, 3]
.