HOWTO · JavaScript

Comment comparer deux tableaux en JavaScript

Ce tutoriel présente quelques méthodes pour comparer deux tableaux en JavaScript

Sur cette page

En JavaScript, l’opérateur === compare les tableaux par identité : deux tableaux créés séparément ne sont donc pas égaux selon cette comparaison, même s’ils contiennent les mêmes valeurs. Pour comparer leur contenu, choisissez une règle pour l’ordre et les valeurs des éléments. Si les valeurs primitives sont dans le même ordre, comparez les longueurs, puis chaque élément à la même position. Utilisez JSON.stringify() uniquement si ses règles de sérialisation conviennent à vos données ; si l’ordre importe peu, comparez des copies triées. Ces méthodes de base comparent les tableaux et objets imbriqués par référence, et non par structure.

Que signifie l’égalité de deux tableaux ?

Commencez par définir ce que signifie « égal » pour votre cas. Une comparaison ordonnée exige la même longueur et une correspondance à chaque indice. Une comparaison indépendante de l’ordre traite les tableaux comme des collections, mais doit tout de même tenir compte des valeurs en double : [1, 1, 2] n’équivaut pas à [1, 2, 2] simplement parce que les deux tableaux contiennent les mêmes valeurs distinctes.

Déterminez aussi si l’égalité des éléments doit être superficielle ou structurelle. L’égalité stricte convient pour comparer des valeurs primitives telles que des nombres et des chaînes. Pour les objets et les tableaux imbriqués, elle vérifie si les deux positions font référence au même objet ; elle ne compare ni ses propriétés ni son contenu imbriqué.

Comparer des tableaux dans l’ordre avec une boucle ou Array.prototype.every()

Une fonction autonome évite de modifier le prototype intégré Array.prototype. Cette version vérifie d’abord la longueur, puis compare les valeurs correspondantes avec l’égalité stricte. Il s’agit d’une comparaison ordonnée et superficielle.

Exécutez cet exemple :

Le code et les libellés ou sorties affichés dans cette section restent en anglais.

function arraysEqual(left, right) {
  if (left.length !== right.length) return false;
  return left.every((value, index) => value === right[index]);
}

const first = ["red", "green", "blue"];
const second = ["red", "green", "blue"];
console.log(arraysEqual(first, second));
true

La fonction rejette aussi une valeur modifiée et des tableaux de longueurs différentes. Les appels suivants sont des exemples non exécutés :

function arraysEqual(left, right) {
  if (left.length !== right.length) return false;
  return left.every((value, index) => value === right[index]);
}

console.log(arraysEqual(["red", "green"], ["red", "blue"]));
console.log(arraysEqual(["red", "green"], ["red", "green", "blue"]));

Le premier appel renvoie false parce que les deuxièmes éléments diffèrent ; le second renvoie false parce que les longueurs sont différentes.

Une boucle for permet d’appliquer la même règle si vous souhaitez personnaliser la comparaison à chaque indice : rejetez les tableaux de longueurs différentes, renvoyez false dès la première différence et renvoyez true une fois toutes les positions vérifiées. Array.prototype.every() est plus concis et s’arrête dès que son rappel renvoie false. Cette méthode ignore les emplacements non attribués des tableaux creux ; son résultat peut donc différer de celui d’une boucle qui lit chaque indice. Utilisez des tableaux denses ou définissez une règle pour les emplacements vides si cette différence compte.

Comparer des tableaux avec JSON.stringify()

Pour des tableaux contenant des valeurs compatibles avec JSON, comparer leurs formes sérialisées est concis : JSON.stringify(left) === JSON.stringify(right). La comparaison tient compte de l’ordre : [1, 2] et [2, 1] donnent donc des résultats différents. La sérialisation suit aussi des règles précises : les valeurs non prises en charge, comme undefined dans un tableau, sont sérialisées en null, tandis que les propriétés d’objet dont la valeur est undefined sont omises. Des objets distincts ayant des propriétés sérialisables équivalentes peuvent produire la même chaîne, mais cela ne définit pas une égalité profonde générale. L’ordre des propriétés et le comportement d’une sérialisation personnalisée peuvent également influer sur le résultat. Choisissez cette méthode uniquement si ces règles conviennent au contrat de vos données ; ne l’utilisez pas comme vérification universelle de l’égalité et ne supposez pas qu’elle est plus rapide pour les grands tableaux.

Comparer des tableaux sans tenir compte de l’ordre

Si l’ordre n’a pas d’importance et que les éléments sont des valeurs primitives, triez des copies superficielles et comparez les éléments aux positions correspondantes. Appeler sort() directement sur les entrées les modifierait ; copiez-les donc d’abord avec slice(). Le tri par défaut compare les représentations sous forme de chaînes ; fournissez un comparateur si les valeurs exigent un autre ordre, par exemple des nombres. Le tri demande du travail supplémentaire, et les types mixtes nécessitent une règle d’ordre explicite. Les vérifications de longueur et des éléments tiennent toujours compte du nombre d’occurrences de chaque valeur.

Pour des chaînes primitives, triez les copies et comparez chaque valeur obtenue avec l’égalité stricte. Cet exemple complet, non exécuté, affiche le résultat de la comparaison et les deux tableaux d’origine :

Le code et les libellés ou sorties affichés dans cette section restent en anglais.

function arraysHaveSameValues(left, right) {
  if (left.length !== right.length) return false;
  const sortedLeft = left.slice().sort();
  const sortedRight = right.slice().sort();
  return sortedLeft.every((value, index) => value === sortedRight[index]);
}

const left = ["pear", "apple", "pear"];
const right = ["pear", "pear", "apple"];
console.log(arraysHaveSameValues(left, right));
console.log(left);
console.log(right);

Pour ces tableaux, la règle de comparaison renvoie true, et le tri des copies laisse les deux entrées dans leur ordre initial. Trier les deux copies puis comparer chaque position tient également compte du nombre d’occurrences : des tableaux contenant un nombre différent d’une valeur ne correspondent pas. Le tri par défaut et l’égalité stricte conviennent ici aux chaînes ; les types mixtes nécessitent un comparateur et une règle d’égalité adaptés à leurs types. Pour les objets, définissez une clé qui représente l’égalité recherchée ou utilisez une stratégie de mise en correspondance conçue pour ces valeurs ; le tri par défaut ne définit pas l’égalité des objets.

Traiter les tableaux et les objets imbriqués

Les exemples de comparaison ordonnée et de tri utilisent l’égalité stricte pour chaque élément. Ainsi, deux valeurs créées séparément, comme [{ id: 1 }], sont considérées comme différentes à cette position, même si leurs propriétés visibles sont identiques. Il en va de même pour les tableaux imbriqués. Si une égalité structurelle est nécessaire, utilisez une comparaison récursive qui définit le comportement pour chaque type pris en charge, ou une bibliothèque d’égalité profonde conçue pour votre application. Avant de vous y fier, précisez le traitement attendu pour les dates, les maps, les sets, les prototypes, les références cycliques et les valeurs numériques particulières ; les outils d’égalité profonde peuvent appliquer des règles différentes.

Pour des données dont la compatibilité avec JSON est garantie, la sérialisation peut parfois fournir une comparaison structurelle concise, sous réserve des limites décrites plus haut. Sinon, définissez explicitement la règle d’égalité et testez les cas pertinents pour l’application. En pratique, choisissez la méthode la plus simple qui respecte les exigences d’ordre et de sémantique des valeurs : every() ou une boucle pour des valeurs primitives ordonnées, la sérialisation pour des données JSON soumises à des contraintes adaptées, et une stratégie explicite de mise en correspondance ou d’égalité profonde pour les autres besoins.