比较JavaScript中的对象数组
我想比较JavaScript代码中的两个对象数组。这些对象总共有8个属性,但每个对象的每个属性都不会有一个值,而且数组的每个属性都不会大于8个项目,因此可能遍历每个属性然后查看8个属性的值的蛮力方法是我想要做的最简单的方法,但在实现之前,我想看看是否有人有更优雅的解决方案。有什么想法吗?编辑:在当前基于浏览器的JavaScript解释器实现中,不能重载运算符 要回答最初的问题,有一种方法可以做到这一点,请注意,这有点像黑客,只需比较两个JSON字符串。这将简单地告诉您数组是否不同,显然您也可以对数组中的每个对象执行此操作,以查看哪些对象不同 另一个选择是使用一个库,它有一些比较对象的好工具——我使用并推荐比较JavaScript中的对象数组,javascript,arrays,comparison,Javascript,Arrays,Comparison,我想比较JavaScript代码中的两个对象数组。这些对象总共有8个属性,但每个对象的每个属性都不会有一个值,而且数组的每个属性都不会大于8个项目,因此可能遍历每个属性然后查看8个属性的值的蛮力方法是我想要做的最简单的方法,但在实现之前,我想看看是否有人有更优雅的解决方案。有什么想法吗?编辑:在当前基于浏览器的JavaScript解释器实现中,不能重载运算符 要回答最初的问题,有一种方法可以做到这一点,请注意,这有点像黑客,只需比较两个JSON字符串。这将简单地告诉您数组是否不同,显然您也可以对
编辑:也值得考虑,因为比较两个给定对象的单个函数要比执行我建议的任何库小得多(尽管我的建议肯定会很有效) 下面是一个简单的实现,可能对您来说已经足够了-请注意,此实现存在潜在的问题:
function objectsAreSame(x, y) {
var objectsAreSame = true;
for(var propertyName in x) {
if(x[propertyName] !== y[propertyName]) {
objectsAreSame = false;
break;
}
}
return objectsAreSame;
}
假设两个对象具有相同的属性列表
哦,很明显,不管是好是坏,我属于唯一一个返回点阵营 老实说,每个对象最多有8个对象,每个对象最多有8个属性,最好的办法就是遍历每个对象并直接进行比较。这会很快也很容易
如果你打算经常使用这些类型的比较,那么我同意Jason关于JSON序列化的看法……但除此之外,没有必要使用新的库或JSON序列化代码来降低你的应用程序的速度。在@JasonBunting的回答中提到的
objectsAreSame
函数对我来说很好。但是,有一个小问题:如果x[propertyName]
和y[propertyName]
是对象(typeof x[propertyName]==“object”
),您需要递归调用函数来比较它们。我研究了一个简单的算法来比较两个对象的内容并返回一个可理解的差异列表。我想我会分享。它借鉴了jQuery的一些思想,即map
函数实现以及对象和数组类型检查
它返回一个“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;
}
//比较两个对象的内容并返回差异列表
//返回一个数组,其中每个元素也是以下形式的数组:
//[访问器,diffType,leftValue,rightValue]
//
//diffType是以下类型之一:
//值:当该索引处的基元值不同时
//未定义:当索引中的值存在于一个对象中但不存在于
//另一个;其中一个值始终未定义
//null:当该索引中的值为null或未定义时;价值观是
//表示为布尔值,表示它们是否为空
//类型:当该索引中的值属于不同类型时;价值观是
//表示为类型
//长度:当该索引中的数组长度不同时;价值观是
//数组的长度
//
功能对象(o1,o2){
//选择一个map()impl。
//如果愿意,可以使用jQuery中的$.map
var map=Array.prototype.map?
函数(a){return Array.prototype.map.apply(a,Array.prototype.slice.call(arguments,1));}:
函数(a,f){
var ret=新数组(a.length),值;
对于(变量i=0,长度=a.length;i 对于(var i=0;i我知道这是一个老问题,提供的答案可以很好地解决……但这稍微短了一点,不需要任何额外的库(即JSON):
请试试这个:
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;
}
}
下面是我的尝试,使用+npm包
我假设您希望检查两个数组是否包含相同的对象,即使这些对象在两个数组之间的顺序不同
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);
});
}
我尝试了JSON.stringify()
并为我工作
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
使用lodash的\部分:
由于序列化通常不起作用(仅当属性顺序匹配时:JSON.stringify({a:1,b:2})!==JSON.stringify({b:2,a:1})
),您必须检查属性计数并比较每个属性:
const objectsEqual=(o1,o2)=>
Object.keys(o1).length==Object.keys(o2).length
&&Object.keys(o1).every(p=>o1[p]==o2[p]);
const obj1={姓名:'John',年龄:33};
const obj2={age:33,name:'John'};
const obj3={姓名:'John',年龄:45};
log(objectsEqual(obj1,obj2));//true
log(objectsEqual(obj1,obj3));//false
与json进行比较非常糟糕。请尝试使用此包来比较嵌套
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
const array1AndArray2NotEqual =
_.some(array1, (a1, idx) => a1.key1 !== array2[idx].key1
|| a1.key2 !== array2[idx].key2
|| a1.key3 !== array2[idx].key3);
const objectsEqual = (o1, o2) => {
if (o2 === null && o1 !== null) return false;
return o1 !== null && 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 !== null && Array.isArray(o1) && Array.isArray(o2) && !o1.length &&
!o2.length) ? true : o1 === o2;
}
const array1 = [{a: 1}, {b: 2}, { c: 0, d: { e: 1, f: 2, } }, [1,2,3,54]];
const array2 = [{a: 1}, {b: 2}, { c: 0, d: { e: 1, f: 2, } }, [1,2,3,54]];
const arraysCompare = (a1, a2) => {
if (a1.length !== a2.length) return false;
const objectIteration = (object) => {
const result = [];
const objectReduce = (obj) => {
for (let i in obj) {
if (typeof obj[i] !== 'object') {
result.push(`${i}${obj[i]}`);
} else {
objectReduce(obj[i]);
}
}
};
objectReduce(object);
return result;
};
const reduceArray1 = a1.map(item => {
if (typeof item !== 'object') return item;
return objectIteration(item).join('');
});
const reduceArray2 = a2.map(item => {
if (typeof item !== 'object') return item;
return objectIteration(item).join('');
});
const compare = reduceArray1.map(item => reduceArray2.includes(item));
return compare.reduce((acc, item) => acc + Number(item)) === a1.length;
};
console.log(arraysCompare(array1, array2));
const obj1 = { name: 'John', age: 33};
const obj2 = { age: 33, name: 'John' };
const obj3 = { name: 'John', age: 45 };
const equalObjs = ( obj1, obj2 ) => {
let keyExist = false;
for ( const [key, value] of Object.entries(obj1) ) {
// Search each key in reference object and attach a callback function to
// compare the two object keys
if( Object.keys(obj2).some( ( e ) => e == key ) ) {
keyExist = true;
}
}
return keyExist;
}
console.info( equalObjs( obj1, obj2 ) );
const equalArrays = ( arr1, arr2 ) => {
// If the arrays are different length we an eliminate immediately
if( arr1.length !== arr2.length ) {
return false;
} else if ( arr1.every(( obj, index ) => equalObjs( obj, arr2[index] ) ) ) {
return true;
}
}
console.info( equalArrays( arr1, arr2 ) );