我有两个对象:oldObj
和newObj
。
输入的数据oldObj
用于填充表单,newObj
是用户更改此表单中的数据并提交后的结果。
两个物体都很深,即。它们具有对象或对象数组等属性-它们的深度可以为n级,因此diff算法需要递归。
现在我需要不只是从弄清楚什么改变(如添加/更新/删除)oldObj
来newObj
,却怎么也最能代表它。
到目前为止,我的想法只是建立一个genericDeepDiffBetweenObjects
将在表单上返回对象的方法,{add:{...},upd:{...},del:{...}}
但随后我想到:之前一定有人需要此方法。
那么…是否有人知道可以做到这一点的库或一段代码,也许有一种更好的方式来表示差异(以仍可序列化JSON的方式)?
我想过一种更好的方式来表示更新的数据,方法是使用与相同的对象结构newObj
,但将所有属性值都转换为表单上的对象:
{type: '<update|create|delete>', data: <propertyValue>}
所以如果newObj.prop1 = 'new value'
和oldObj.prop1 = 'old value'
它将设置returnObj.prop1 = {type: 'update', data: 'new value'}
当我们进入数组的属性时,它确实变得毛茸茸,因为该数组[1,2,3]
应被视为等于[2,3,1]
,对于基于值的类型(如string,int和bool)的数组而言,这足够简单,但是当涉及到引用类型的数组,例如对象和数组。
应该找到相等的示例数组:
[1,[{c: 1},2,3],{a:'hey'}] and [{a:'hey'},1,[3,{c: 1},2]]
检查这种类型的深价值平等不仅很复杂,而且要找到一种表示可能发生的变化的好方法。
我写了一个小班,可以做您想做的事,您可以在这里进行测试。
与您的建议唯一不同的是,我认为不[1,[{c: 1},2,3],{a:'hey'}] and [{a:'hey'},1,[3,{c: 1},2]]
一样,因为我认为如果数组的元素顺序不相同,数组就不相等。当然,如果需要,可以更改。同样,可以进一步增强此代码以将函数用作参数,该参数将用于基于传递的原始值以任意方式格式化diff对象(现在,此工作由“
compareValues”方法完成)。
var deepDiffMapper = function () {
return {
VALUE_CREATED: 'created',
VALUE_UPDATED: 'updated',
VALUE_DELETED: 'deleted',
VALUE_UNCHANGED: 'unchanged',
map: function(obj1, obj2) {
if (this.isFunction(obj1) || this.isFunction(obj2)) {
throw 'Invalid argument. Function given, object expected.';
}
if (this.isValue(obj1) || this.isValue(obj2)) {
return {
type: this.compareValues(obj1, obj2),
data: obj1 === undefined ? obj2 : obj1
};
}
var diff = {};
for (var key in obj1) {
if (this.isFunction(obj1[key])) {
continue;
}
var value2 = undefined;
if (obj2[key] !== undefined) {
value2 = obj2[key];
}
diff[key] = this.map(obj1[key], value2);
}
for (var key in obj2) {
if (this.isFunction(obj2[key]) || diff[key] !== undefined) {
continue;
}
diff[key] = this.map(undefined, obj2[key]);
}
return diff;
},
compareValues: function (value1, value2) {
if (value1 === value2) {
return this.VALUE_UNCHANGED;
}
if (this.isDate(value1) && this.isDate(value2) && value1.getTime() === value2.getTime()) {
return this.VALUE_UNCHANGED;
}
if (value1 === undefined) {
return this.VALUE_CREATED;
}
if (value2 === undefined) {
return this.VALUE_DELETED;
}
return this.VALUE_UPDATED;
},
isFunction: function (x) {
return Object.prototype.toString.call(x) === '[object Function]';
},
isArray: function (x) {
return Object.prototype.toString.call(x) === '[object Array]';
},
isDate: function (x) {
return Object.prototype.toString.call(x) === '[object Date]';
},
isObject: function (x) {
return Object.prototype.toString.call(x) === '[object Object]';
},
isValue: function (x) {
return !this.isObject(x) && !this.isArray(x);
}
}
}();
var result = deepDiffMapper.map({
a: 'i am unchanged',
b: 'i am deleted',
e: {
a: 1,
b: false,
c: null
},
f: [1, {
a: 'same',
b: [{
a: 'same'
}, {
d: 'delete'
}]
}],
g: new Date('2017.11.25')
}, {
a: 'i am unchanged',
c: 'i am created',
e: {
a: '1',
b: '',
d: 'created'
},
f: [{
a: 'same',
b: [{
a: 'same'
}, {
c: 'create'
}]
}, 1],
g: new Date('2017.11.25')
});
console.log(result);
问题内容: ‘Go’的新手。问题可能是最基本的问题。 我有两个time.Time对象,我想获得小时/分钟/秒这两者之间的差异。可以说: 在上述情况下,由于差为0。应该给我00:00:00。考虑另一种情况: 在这种情况下,差异将为00:05:41。我看了看https://godoc.org/time,但什么都做不了。 问题答案: 您可以用来获取2个值之间的差,结果将是的值。 打印时,格式本身会“智能
问题内容: 我有以下两个数组。我想要这两个数组之间的区别。也就是说,如何找到两个数组都不存在的值? 问题答案: 注意: 这个答案将返回的值是不存在的,它不会返回值不在。
问题内容: 我使用以下代码在Android中使用Gson比较了两个JSON对象: 有两种方法可以使用Gson以JSON格式获取两个对象之间的 差异 吗? 问题答案: 如果将对象反序列化为,也可以使用Guava,则可以用来比较两个生成的地图。 请注意,如果您关心元素的 顺序 ,则不会保留s 字段的顺序,因此此方法不会显示这些比较。 这是您的操作方式: 该程序输出: 在此处阅读更多有关结果对象包含哪些
问题内容: 我希望能够获得两个JavaScript对象图之间所有差异的列表,以及出现变化的属性名称和值。 就其价值而言,这些对象通常以JSON的形式从服务器中检索,并且通常不超过几层深度(即,可能是对象本身具有数据的数组,然后是具有其他数据对象的数组)。 我不仅要看到对基本属性的更改,还要看到数组成员等的数量差异等。 如果没有答案,我可能最终会自己写这个,但希望有人已经完成了这项工作或知道有人做了
问题内容: 我有两个这样的结果集: 我需要的最终结果是这些数组之间的差异–最终结果应如下所示: 是否可以在JavaScript中执行类似的操作? 问题答案: 仅使用本机JS,类似的方法将起作用:
我的问题是,我要比较Java中的两个ArrayList 例如 通过比较方法,我知道这些数组是不同的 (如果数组具有相同的元素,即使它们的顺序不同,我的方法也返回false,如果它们具有相同的元素,则返回true) 因此,该方法将返回FALSE 我的问题是: 请注意,我将在这些ArrayList中包含多个对象,而且方法效率也很重要(不是很重要,但至少很重要)。我在这里看到了答案,但我不确定哪一个更好