在JavaScript中比较对象的数组
我想比较JavaScript代码中的2个对象数组。 这些对象总共有8个属性,但是每个对象都不会有每个对象的值,并且每个对象的数组永远也不会超过8个,所以也许可以使用遍历每个对象的强制方法,然后查看8个属性是做我想做的最简单的方法,但在实施之前,我想看看是否有人有一个更优雅的解决scheme。 有什么想法吗?
编辑:你不能重载操作符在JavaScript解释器的当前常见的基于浏览器的实现。
要回答最初的问题,有一种方法可以做到这一点,并且介意你,这有点破解,只需将两个数组序列化为JSON ,然后比较两个JSONstring即可。 这只会告诉你,如果数组是不同的,显然你可以做到这一点对数组中的每个对象以及看哪些是不同的。
另一个select是使用一个图书馆,有一些很好的设施比较对象 – 我使用和推荐MochiKit 。
编辑: 答案kamens也值得考虑,因为一个函数来比较两个给定的对象将比任何图书馆做我build议(虽然我的build议肯定会工作得很好)小得多。
这是一个天真的实现,可能对你来说足够了 – 要意识到这个实现有潜在的问题:
function objectsAreSame(x, y) { var objectsAreSame = true; for(var propertyName in x) { if(x[propertyName] !== y[propertyName]) { objectsAreSame = false; break; } } return objectsAreSame; }
假定两个对象具有相同的属性确切列表。
哦,可能很明显,无论好坏,我属于唯一的一个回归点阵营。 🙂
我知道这是一个古老的问题,答案提供了很好的工作…但是这有点短,不需要任何额外的库(即JSON):
function arraysAreEqual(ary1,ary2){ return (ary1.join('') == ary2.join('')); }
老实说,每个对象最多有8个对象,每个对象最多有8个属性,最好的办法就是遍历每个对象并直接进行比较。 它会很快,而且会很容易。
如果您打算经常使用这些types的比较,那么我同意Jason关于JSON序列化的内容……但是除此之外,不需要用新的库或JSON序列化代码来减慢您的应用程序的速度。
我用了一个简单的algorithm来比较两个对象的内容,并返回一个可理解的差异列表。 以为我会分享。 它借鉴了jQuery的一些想法,即地图function实现和对象和数组types检查。
它返回一个“diff对象”的列表,它是与diff信息相关的数组。 这很简单。
这里是:
// 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; }
Jason的答案中提到的objectsAreSame函数对我来说工作的很好。 但是,有一个小问题:如果x[propertyName]
和y[propertyName]
是对象( typeof x[propertyName] == 'object'
),则需要recursion调用函数以便比较它们。
请试试这个:
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; } }
这里是我的尝试,使用Node的assert模块 + npm包对象哈希 。
我想你想检查两个数组是否包含相同的对象,即使这些对象在两个数组之间的sorting不同。
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); }); }