Frage

Ich möchte zwei Arrays von Objekten im JavaScript-Code vergleichen.Die Objekte haben insgesamt 8 Eigenschaften, aber nicht jedes Objekt hat einen Wert für jedes, und die Arrays werden nie größer als jeweils 8 Elemente sein, also vielleicht die Brute-Force-Methode, jedes zu durchlaufen und dann die Werte der zu betrachten 8 Eigenschaften sind der einfachste Weg, das zu tun, was ich tun möchte, aber vor der Implementierung wollte ich sehen, ob jemand eine elegantere Lösung hat.Irgendwelche Gedanken?

War es hilfreich?

Lösung

BEARBEITEN:Sie können Operatoren in aktuellen, gängigen browserbasierten Implementierungen von JavaScript-Interpretern nicht überladen.

Um die ursprüngliche Frage zu beantworten: Es gibt eine Möglichkeit, dies zu tun, und wohlgemerkt, das ist einfach ein kleiner Trick Serialisieren Sie die beiden Arrays in JSON und vergleichen Sie dann die beiden JSON-Strings.Das würde Ihnen einfach sagen, ob die Arrays unterschiedlich sind. Natürlich könnten Sie dies tun jede der Objekte innerhalb der Arrays, um zu sehen, welche unterschiedlich waren.

Eine andere Möglichkeit besteht darin, eine Bibliothek zu verwenden, die über einige nette Möglichkeiten zum Vergleichen von Objekten verfügt – ich verwende und empfehle sie MochiKit.


BEARBEITEN: Die Antwort gab Kamens verdient ebenfalls Beachtung, da eine einzelne Funktion zum Vergleichen zweier gegebener Objekte viel kleiner wäre als jede Bibliothek, die das tun würde, was ich vorschlage (obwohl mein Vorschlag sicherlich gut genug funktionieren würde).

Hier ist eine naive Implementierung, die möglicherweise gerade genug für Sie tut – seien Sie sich bewusst, dass es bei dieser Implementierung potenzielle Probleme gibt:

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

Es wird davon ausgegangen, dass beide Objekte genau dieselbe Liste von Eigenschaften haben.

Oh, und es ist wahrscheinlich offensichtlich, dass ich im Guten wie im Schlechten zum Lager mit den einzigen Rückkehrpunkten gehöre.:) :)

Andere Tipps

Ich weiß, dass dies eine alte Frage ist und die bereitgestellten Antworten funktionieren gut ...Dies ist jedoch etwas kürzer und erfordert keine zusätzlichen Bibliotheken (z. B.JSON):

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

Ehrlich gesagt, bei maximal 8 Objekten und maximal 8 Eigenschaften pro Objekt ist es am besten, einfach jedes Objekt zu durchlaufen und die Vergleiche direkt durchzuführen.Es wird schnell gehen und es wird einfach sein.

Wenn Sie diese Art von Vergleichen häufig verwenden, stimme ich Jason in Bezug auf die JSON-Serialisierung zu … aber ansonsten besteht keine Notwendigkeit, Ihre App mit einer neuen Bibliothek oder einem neuen JSON-Serialisierungscode zu verlangsamen.

Ich habe ein wenig an einem einfachen Algorithmus gearbeitet, um den Inhalt zweier Objekte zu vergleichen und eine verständliche Liste der Unterschiede zurückzugeben.Ich dachte, ich würde es teilen.Es übernimmt einige Ideen für jQuery, nämlich die map Funktionsimplementierung und die Objekt- und Array-Typprüfung.

Es wird eine Liste von „Diff-Objekten“ zurückgegeben, bei denen es sich um Arrays mit den Diff-Informationen handelt.Es ist sehr einfach.

Hier ist es:

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

Ich habe es versucht JSON.stringify() und hat bei mir funktioniert.

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

Da die Serialisierung im Allgemeinen nicht funktioniert (nur wenn die Reihenfolge der Eigenschaften übereinstimmt: JSON.stringify({a:1,b:2}) !== JSON.stringify({b:2,a:1})) müssen Sie die Anzahl der Eigenschaften überprüfen und auch jede Eigenschaft vergleichen:

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

Wenn Sie einen umfassenden Vergleich benötigen, können Sie die Funktion rekursiv aufrufen:

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

Dann ist es einfach, diese Funktion zum Vergleichen von Objekten in Arrays zu verwenden:

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

Probieren Sie mal das hier an:

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

Hier ist mein Versuch, mit Assert-Modul des Knotens + npm-Paket Objekt-Hash.

Ich gehe davon aus, dass Sie überprüfen möchten, ob zwei Arrays dieselben Objekte enthalten, auch wenn diese Objekte zwischen den beiden Arrays unterschiedlich angeordnet sind.

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

Der objectsAreSame Die in der Antwort von @JasonBunting erwähnte Funktion funktioniert für mich einwandfrei.Allerdings gibt es ein kleines Problem:Wenn x[propertyName] Und y[propertyName] sind Objekte (typeof x[propertyName] == 'object'), müssen Sie die Funktion rekursiv aufrufen, um sie zu vergleichen.

verwenden _.some von 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);
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top