Comparando matrizes de objects em JavaScript

Eu quero comparar duas matrizes de objects no código JavaScript. Os objects têm 8 propriedades totais, mas cada object não terá um valor para cada, e os arrays nunca serão maiores do que 8 itens cada, então talvez o método de força bruta percorra cada um deles e, em seguida, observe os valores do 8 propriedades é a maneira mais fácil de fazer o que eu quero fazer, mas antes de implementar, eu queria ver se alguém tinha uma solução mais elegante. Alguma ideia?

EDIT: Você não pode sobrecarregar os operadores em implementações atuais baseadas em navegador comuns de intérpretes de JavaScript.

Para responder a pergunta original, uma maneira de fazer isso e pensar em você é um truque, simplesmente serialize os dois arrays em JSON e compare os dois strings JSON. Isso simplesmente diria a você se as matrizes são diferentes, obviamente, você poderia fazer isso para cada um dos objects dentro das matrizes, bem como para ver quais eram diferentes.

Outra opção é usar uma biblioteca que tenha ótimos resources para comparar objects – eu uso e recomendo o MochiKit .


EDIT: A resposta kamens deu também merece consideração, uma vez que uma única function para comparar dois objects dados seria muito menor do que qualquer biblioteca para fazer o que eu sugiro (embora minha sugestão certamente funcionaria bem o suficiente).

Aqui está uma implementação ingênua que pode fazer apenas o suficiente para você – esteja ciente de que há problemas potenciais com essa implementação:

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

A suposição é que ambos os objects têm a mesma lista exata de propriedades.

Ah, e é óbvio que, para melhor ou para pior, eu pertenço ao acampamento de um único ponto de retorno. 🙂

Eu sei que esta é uma pergunta antiga e as respostas fornecidas funcionam bem … mas isso é um pouco mais curto e não requer nenhuma biblioteca adicional (ou seja, JSON):

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

Honestamente, com 8 objects no máximo e 8 propriedades no máximo por object, sua melhor aposta é atravessar cada object e fazer as comparações diretamente. Vai ser rápido e vai ser fácil.

Se você estiver usando esses tipos de comparações com frequência, concordo com Jason sobre a serialização JSON … mas, caso contrário, não há necessidade de desacelerar seu aplicativo com uma nova biblioteca ou um código de serialização JSON.

Eu trabalhei um pouco em um algoritmo simples para comparar o conteúdo de dois objects e retornar uma lista inteligível de diferença. Pensei que eu iria compartilhar. Ele empresta algumas idéias para o jQuery, ou seja, a implementação da function map e a verificação do tipo de object e matriz.

Ele retorna uma lista de “objects diff”, que são arrays com a informação diff. É muito simples.

Aqui está:

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

Tente este, por favor:

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

Aqui está a minha tentativa, usando o módulo de declaração do Node + npm package object-hash .

Suponho que você gostaria de verificar se duas matrizes contêm os mesmos objects, mesmo se esses objects forem ordenados de maneira diferente entre as duas matrizes.

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

A function objectsAreSame mencionada na resposta do @ JasonBunting funciona bem para mim. No entanto, há um pequeno problema: Se x[propertyName] e y[propertyName] são objects ( typeof x[propertyName] == 'object' ), você precisará chamar a function recursivamente para compará-los.