Question

Je souhaite comparer 2 tableaux d'objets dans du code JavaScript.Les objets ont 8 propriétés au total, mais chaque objet n'aura pas de valeur pour chacun, et les tableaux ne seront jamais plus grands que 8 éléments chacun, alors peut-être que la méthode par force brute consiste à parcourir chacun puis à examiner les valeurs du 8 propriétés est le moyen le plus simple de faire ce que je veux faire, mais avant de l'implémenter, je voulais voir si quelqu'un avait une solution plus élégante.Des pensées?

Était-ce utile?

La solution

MODIFIER:Vous ne pouvez pas surcharger les opérateurs dans les implémentations actuelles et courantes des interpréteurs JavaScript basées sur un navigateur.

Pour répondre à la question initiale, une façon de procéder, et attention, c'est un peu un hack, simplement sérialiser les deux tableaux en JSON puis comparez les deux chaînes JSON.Cela vous dirait simplement si les tableaux sont différents, vous pouvez évidemment le faire pour chaque des objets dans les tableaux également pour voir lesquels étaient différents.

Une autre option consiste à utiliser une bibliothèque dotée de fonctionnalités intéressantes pour comparer des objets - j'utilise et recommande MochiKit.


MODIFIER: La réponse donnée par Kamens mérite également d'être pris en considération, car une seule fonction permettant de comparer deux objets donnés serait beaucoup plus petite que n'importe quelle bibliothèque pour faire ce que je suggère (même si ma suggestion fonctionnerait certainement assez bien).

Voici une implémentation naïve qui peut faire juste ce qu'il vous faut - sachez qu'il existe des problèmes potentiels avec cette implémentation :

function objectsAreSame(x, y) {
   var objectsAreSame = true;
   for(var propertyName in x) {
      if(x[propertyName] !== y[propertyName]) {
         objectsAreSame = false;
         break;
      }
   }
   return objectsAreSame;
}

L’hypothèse est que les deux objets ont exactement la même liste de propriétés.

Oh, et il est probablement évident que, pour le meilleur ou pour le pire, j’appartiens au camp du seul point de retour.:)

Autres conseils

Je sais que c'est une vieille question et les réponses fournies fonctionnent bien...mais c'est un peu plus court et ne nécessite aucune bibliothèque supplémentaire (c'est-à-direJSON ):

function arraysAreEqual(ary1,ary2){
  return (ary1.join('') == ary2.join(''));
}

Honnêtement, avec 8 objets maximum et 8 propriétés maximum par objet, le mieux est de simplement parcourir chaque objet et de faire les comparaisons directement.Ce sera rapide et ce sera facile.

Si vous envisagez d'utiliser souvent ces types de comparaisons, alors je suis d'accord avec Jason à propos de la sérialisation JSON... mais sinon, il n'est pas nécessaire de ralentir votre application avec une nouvelle bibliothèque ou un nouveau code de sérialisation JSON.

J'ai travaillé un peu sur un algorithme simple pour comparer le contenu de deux objets et renvoyer une liste intelligible de différence.Je pensais que je partagerais.Il emprunte quelques idées à jQuery, à savoir le map l'implémentation des fonctions et la vérification des types d'objets et de tableaux.

Il renvoie une liste d'"objets diff", qui sont des tableaux contenant les informations de différence.C'est très simple.

C'est ici:

// compare contents of two objects and return a list of differences
// returns an array where each element is also an array in the form:
// [accessor, diffType, leftValue, rightValue ]
//
// diffType is one of the following:
//   value: when primitive values at that index are different
//   undefined: when values in that index exist in one object but don't in 
//              another; one of the values is always undefined
//   null: when a value in that index is null or undefined; values are
//         expressed as boolean values, indicated wheter they were nulls
//   type: when values in that index are of different types; values are 
//         expressed as types
//   length: when arrays in that index are of different length; values are
//           the lengths of the arrays
//

function DiffObjects(o1, o2) {
    // choose a map() impl.
    // you may use $.map from jQuery if you wish
    var map = Array.prototype.map?
        function(a) { return Array.prototype.map.apply(a, Array.prototype.slice.call(arguments, 1)); } :
        function(a, f) { 
            var ret = new Array(a.length), value;
            for ( var i = 0, length = a.length; i < length; i++ ) 
                ret[i] = f(a[i], i);
            return ret.concat();
        };

    // shorthand for push impl.
    var push = Array.prototype.push;

    // check for null/undefined values
    if ((o1 == null) || (o2 == null)) {
        if (o1 != o2)
            return [["", "null", o1!=null, o2!=null]];

        return undefined; // both null
    }
    // compare types
    if ((o1.constructor != o2.constructor) ||
        (typeof o1 != typeof o2)) {
        return [["", "type", Object.prototype.toString.call(o1), Object.prototype.toString.call(o2) ]]; // different type

    }

    // compare arrays
    if (Object.prototype.toString.call(o1) == "[object Array]") {
        if (o1.length != o2.length) { 
            return [["", "length", o1.length, o2.length]]; // different length
        }
        var diff =[];
        for (var i=0; i<o1.length; i++) {
            // per element nested diff
            var innerDiff = DiffObjects(o1[i], o2[i]);
            if (innerDiff) { // o1[i] != o2[i]
                // merge diff array into parent's while including parent object name ([i])
                push.apply(diff, map(innerDiff, function(o, j) { o[0]="[" + i + "]" + o[0]; return o; }));
            }
        }
        // if any differences were found, return them
        if (diff.length)
            return diff;
        // return nothing if arrays equal
        return undefined;
    }

    // compare object trees
    if (Object.prototype.toString.call(o1) == "[object Object]") {
        var diff =[];
        // check all props in o1
        for (var prop in o1) {
            // the double check in o1 is because in V8 objects remember keys set to undefined 
            if ((typeof o2[prop] == "undefined") && (typeof o1[prop] != "undefined")) {
                // prop exists in o1 but not in o2
                diff.push(["[" + prop + "]", "undefined", o1[prop], undefined]); // prop exists in o1 but not in o2

            }
            else {
                // per element nested diff
                var innerDiff = DiffObjects(o1[prop], o2[prop]);
                if (innerDiff) { // o1[prop] != o2[prop]
                    // merge diff array into parent's while including parent object name ([prop])
                    push.apply(diff, map(innerDiff, function(o, j) { o[0]="[" + prop + "]" + o[0]; return o; }));
                }

            }
        }
        for (var prop in o2) {
            // the double check in o2 is because in V8 objects remember keys set to undefined 
            if ((typeof o1[prop] == "undefined") && (typeof o2[prop] != "undefined")) {
                // prop exists in o2 but not in o1
                diff.push(["[" + prop + "]", "undefined", undefined, o2[prop]]); // prop exists in o2 but not in o1

            }
        }
        // if any differences were found, return them
        if (diff.length)
            return diff;
        // return nothing if objects equal
        return undefined;
    }
    // if same type and not null or objects or arrays
    // perform primitive value comparison
    if (o1 != o2)
        return [["", "value", o1, o2]];

    // return nothing if values are equal
    return undefined;
}

J'ai essayé JSON.stringify() et a travaillé pour moi.

let array1 = [1,2,{value:'alpha'}] , array2 = [{value:'alpha'},'music',3,4];

JSON.stringify(array1) // "[1,2,{"value":"alpha"}]"

JSON.stringify(array2) // "[{"value":"alpha"},"music",3,4]"

JSON.stringify(array1) === JSON.stringify(array2); // false

Comme la sérialisation ne fonctionne généralement pas (uniquement lorsque l'ordre des propriétés correspond : JSON.stringify({a:1,b:2}) !== JSON.stringify({b:2,a:1})), vous devez vérifier le nombre de propriétés et comparer chaque propriété également :

const objectsEqual = (o1, o2) =>
    Object.keys(o1).length === Object.keys(o2).length 
        && Object.keys(o1).every(p => o1[p] === o2[p]);

const obj1 = { name: 'John', age: 33};
const obj2 = { age: 33, name: 'John' };
const obj3 = { name: 'John', age: 45 };
        
console.log(objectsEqual(obj1, obj2)); // true
console.log(objectsEqual(obj1, obj3)); // false

Si vous avez besoin d'une comparaison approfondie, vous pouvez appeler la fonction de manière récursive :

const obj1 = { name: 'John', age: 33, info: { married: true, hobbies: ['sport', 'art'] } };
const obj2 = { age: 33, name: 'John', info: { hobbies: ['sport', 'art'], married: true } };
const obj3 = { name: 'John', age: 33 };

const objectsEqual = (o1, o2) => 
    typeof o1 === 'object' && Object.keys(o1).length > 0 
        ? Object.keys(o1).length === Object.keys(o2).length 
            && Object.keys(o1).every(p => objectsEqual(o1[p], o2[p]))
        : o1 === o2;
        
console.log(objectsEqual(obj1, obj2)); // true
console.log(objectsEqual(obj1, obj3)); // false

Il est ensuite facile d'utiliser cette fonction pour comparer des objets dans des tableaux :

const arr1 = [obj1, obj1];
const arr2 = [obj1, obj2];
const arr3 = [obj1, obj3];

const arraysEqual = (a1, a2) => 
   a1.length === a2.length && a1.every((o, idx) => objectsEqual(o, a2[idx]));

console.log(arraysEqual(arr1, arr2)); // true
console.log(arraysEqual(arr1, arr3)); // false

S'il vous plaît, essayez celui-la:

function used_to_compare_two_arrays(a, b)
{
  // This block will make the array of indexed that array b contains a elements
  var c = a.filter(function(value, index, obj) {
    return b.indexOf(value) > -1;
  });

  // This is used for making comparison that both have same length if no condition go wrong 
  if (c.length !== a.length) {
    return 0;
  } else{
    return 1;
  }
}

Voici ma tentative, en utilisant Module d'assertion du nœud + paquet npm hachage d'objet.

Je suppose que vous aimeriez vérifier si deux tableaux contiennent les mêmes objets, même si ces objets sont ordonnés différemment entre les deux tableaux.

var assert = require('assert');
var hash = require('object-hash');

var obj1 = {a: 1, b: 2, c: 333},
    obj2 = {b: 2, a: 1, c: 444},
    obj3 = {b: "AAA", c: 555},
    obj4 = {c: 555, b: "AAA"};

var array1 = [obj1, obj2, obj3, obj4];
var array2 = [obj3, obj2, obj4, obj1]; // [obj3, obj3, obj2, obj1] should work as well

// calling assert.deepEquals(array1, array2) at this point FAILS (throws an AssertionError)
// even if array1 and array2 contain the same objects in different order,
// because array1[0].c !== array2[0].c

// sort objects in arrays by their hashes, so that if the arrays are identical,
// their objects can be compared in the same order, one by one
var array1 = sortArrayOnHash(array1);
var array2 = sortArrayOnHash(array2);

// then, this should output "PASS"
try {
    assert.deepEqual(array1, array2);
    console.log("PASS");
} catch (e) {
    console.log("FAIL");
    console.log(e);
}

// You could define as well something like Array.prototype.sortOnHash()...
function sortArrayOnHash(array) {
    return array.sort(function(a, b) {
        return hash(a) > hash(b);
    });
}

Le objectsAreSame la fonction mentionnée dans la réponse de @JasonBunting fonctionne bien pour moi.Il y a cependant un petit problème :Si x[propertyName] et y[propertyName] sont des objets (typeof x[propertyName] == 'object'), vous devrez appeler la fonction de manière récursive afin de les comparer.

en utilisant _.some de lodash : https://lodash.com/docs/4.17.11#some

const array1AndArray2NotEqual = 
          _.some(array1, (a1, idx) => a1.key1 !== array2[idx].key1 
                                     || a1.key2 !== array2[idx].key2 
                                     || a1.key3 !== array2[idx].key3);
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top