gpt4 book ai didi

javascript - 两个对象之间的通用深度差异

转载 作者:IT老高 更新时间:2023-10-28 13:15:26 30 4
gpt4 key购买 nike

我有两个对象:oldObjnewObj

oldObj 中的数据用于填充表单,newObj 是用户更改此表单中的数据并提交的结果。

两个对象都很深,即。它们具有对象或对象数组等属性 - 它们可以是 n 级深,因此 diff 算法需要是递归的。

现在我不仅需要弄清楚从 oldObjnewObj 的更改(如添加/更新/删除),还需要弄清楚如何最好地表示它。

到目前为止,我的想法是构建一个 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: '新值'}

更新 2:

当我们处理数组属性时,它变得非常棘手,因为数组 [1,2,3] 应该被视为等于 [2,3,1],对于基于值类型的数组(如 string、int 和 bool)来说非常简单,但对于引用类型的数组(如对象和数组)则非常难以处理。

应该找到相等的示例数组:

[1,[{c: 1},2,3],{a:'hey'}] and [{a:'hey'},1,[3,{c: 1},2]]

不仅检查这种类型的深度值相等非常复杂,而且找出一种表示可能发生的变化的好方法。

最佳答案

我写了一个小类,做你想做的,你可以测试一下here .

唯一与你的提议不同的是我不考虑

[1,[{c: 1},2,3],{a:'hey'}]

[{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);

关于javascript - 两个对象之间的通用深度差异,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8572826/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com