Domanda

Voglio confrontare 2 array di oggetti nel codice JavaScript.Gli oggetti sono 8 totale proprietà, ma ogni oggetto non sarà un valore per ogni, e gli array non sono mai sta per essere più grande di 8 elementi ciascuna, così, forse, il metodo forza bruta di attraversamento di ogni e poi, guardando i valori delle 8 proprietà è il modo più semplice per fare quello che voglio fare, ma prima di implementare, volevo vedere se qualcuno avesse una soluzione più elegante.Ogni pensiero?

È stato utile?

Soluzione

EDIT:Non è possibile sovraccaricare gli operatori corrente, comuni a tutti i browser basati su implementazioni di JavaScript interpreti.

Per rispondere alla domanda originale, un modo si potrebbe fare questo, e la mente si, questo è un po ' un hack, semplicemente serializzare i due array JSON e, quindi, di confrontare due stringhe JSON.Che sarebbe semplicemente dirvi se le matrici sono diversi, ovviamente si potrebbe fare questo per ogni di oggetti all'interno di matrici e per vedere quelli che erano diverse.

Un'altra opzione è quella di utilizzare una libreria che ha alcune belle camere / strutture per confrontare gli oggetti - uso e raccomandare MochiKit.


EDIT: La risposta kamens ha dato merita considerazione, dal momento che una singola funzione per confrontare due oggetti molto inferiori rispetto a qualsiasi libreria di fare quello che mi suggerisci (anche se il mio suggerimento sarebbe di certo funzionare abbastanza bene).

Qui è un ingenuo implemenation che può fare abbastanza per voi - essere consapevoli che ci sono potenziali problemi con questa implementazione:

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

Il presupposto è che entrambi gli oggetti hanno lo stesso esatto elenco delle proprietà.

Oh, e probabilmente è ovvio che, per meglio o peggio, io sono il solo-un-ritorno-punto di camp.:)

Altri suggerimenti

So che questa è una vecchia questione e le risposte fornite funzionare bene ...ma questo è un po ' più breve e non richiede librerie aggiuntive ( es.JSON ):

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

Onestamente, con 8 oggetti max e 8 proprietà max per oggetto, la vostra scommessa migliore è quello di attraversare ogni oggetto e fare il confronto diretto.Sarà veloce e non sarà facile.

Se si sta andando ad essere utilizzando questi tipi di confronti, spesso, allora sono d'accordo con Jason circa serializzazione JSON...ma per il resto non c'è bisogno di rallentare la tua app con una nuova libreria o JSON, il codice di serializzazione.

Ho lavorato un po ' su un algoritmo semplice per confrontare il contenuto di due oggetti e tornare in forma intelligibile elenco di differenza.Ho pensato di condividere.Si prende in prestito alcune idee per jQuery, vale a dire il map implementazione della funzione e l'oggetto e il tipo di matrice di controllo.

Restituisce un elenco di "diff oggetti", che sono matrici con il diff info.E ' molto semplice.

Qui è:

// 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;
}

Ho provato JSON.stringify() e ha funzionato per me.

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

Come serializzazione non lavoro in genere (solo quando l'ordine di proprietà partite: JSON.stringify({a:1,b:2}) !== JSON.stringify({b:2,a:1})), è necessario controllare il conte di proprietà e confrontare ogni struttura così:

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

Se avete bisogno di un profondo confronto, è possibile chiamare la funzione in modo ricorsivo:

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

Allora è facile utilizzare questa funzione per confrontare gli oggetti in un array:

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

Prova con questo:

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;
  }
}

Qui è il mio tentativo, utilizzando Del nodo di affermare modulo + npm pacchetto oggetto hash.

Suppongo che si desidera controllare se due array contiene gli stessi oggetti, anche se tali oggetti vengono ordinati in modo diverso tra i due array.

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);
    });
}

Il objectsAreSame funzione di cui al @JasonBunting risposta funziona bene per me.Tuttavia, c'è un piccolo problema:Se x[propertyName] e y[propertyName] sono oggetti (typeof x[propertyName] == 'object'), è necessario chiamare la funzione in modo ricorsivo per poterli confrontare.

utilizzando _.some da 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);
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top