gpt4 book ai didi

javascript - 获取两个javascript对象的增量

转载 作者:数据小太阳 更新时间:2023-10-29 05:36:10 25 4
gpt4 key购买 nike

我有两个大的嵌套 javascript 对象,我想比较它们并创建一个仅表示差异的对象。我打算用它来创建 PATCH 请求。

给定 oldObjnewObj:

  • 仅在 newObj 上的属性应该在 diff 中
  • 仅在 oldObj 上的属性应该在 diff 中
  • 如果值是数组、字符串或数字,则两个对象上的属性都应使用 newObj 中的值
  • 应该递归比较对象
  • 无需花哨合并数组,完全替换即可

这看起来像是重复的,但我认为不是。 This solution (1)只有一层深(下面的答案是非递归的,在数组上爆炸,并且不是双向的)。 this solution (2)返回未更改的属性不是双向的。

目标输入/输出:

diff({a:1},{a:0}); // {a:0}

diff({a:1},{b:1}); // {a:1,b:1}

diff({
a: { x: 1 },
b: 1
},
{
a: { x: 0 },
b: 1
}) // {a:{x:0}}

diff({a:[1,3,5,7]},{a:[1,3,7]}); // {a:[1,3,7]}

我正在使用从解决方案 1 修改而来的以下方法。它满足除 diff({a:1},{b:1})//{a:1,b:1} 之外的所有条件 因为它只比较一个方向。

jsonDiff = function(oldObject, newObject) {
var diff, i, innerDiff;
diff = {};
for (i in newObject) {
innerDiff = {};
if (_.isArray(newObject[i])) {
if (!_.isEqual(newObject[i], oldObject[i])) {
diff[i] = newObject[i];
}
} else if (typeof newObject[i] === 'object') {
innerDiff = jsonDiff(oldObject[i], newObject[i]);
if (!_.isEmpty(innerDiff)) {
diff[i] = innerDiff;
}
} else if (!oldObject) {
diff[i] = newObject[i];
} else if (!oldObject.hasOwnProperty(i)) {
diff[i] = newObject[i];
} else if (oldObject[i] !== newObject[i]) {
diff[i] = newObject[i];
}
}
return diff;
};

我看到了 jsonDiffPatch库,但我不需要它创建的所有元数据,只需要原始差异对象。是否有一个迷你图书馆可以做到这一点?似乎有必要很好地实现 PATCH,但我找不到。有人有这方面的小要点吗?

最佳答案

这是一个适合您的函数,注释多于代码:

// diffObjs: return differences between JavaScript values
//
// Function:
//
// Compare two JavaScript values, and return a two-element
// array that contains a minimal representation of the difference
// between the two.
//
// Values may be scalar (e.g., string, integer, boolean) or objects,
// including arrays. When the two values match exactly, that is,
// if the '===' operator between the two would return 'true', we return NULL.
//
// When the result contains an object or array, only data, not references,
// are copied from the arguments. This makes for a large size result
// but one whose manipulation will not affect the original arguments.
//
// Args:
// v1, v2: values to compare
//
// Specific behaviors:
//
// *Return NULL if v1 === v2*
//
// This happens when two scalar (non-object) values match, or when the same
// object or array is passed in both arguments.
// e.g.,
//
// var my_obj = { member1: 0, member1: 'dog' };
// var my_array = [ 1, 'cat' ];
// var my_int = 7;
// var no_val = null;
//
// diffObjs(my_int, my_int) ==> NULL
// diffObjs(1, 1) ==> NULL
// diffObjs(my_obj, my_obj) ==> NULL
// diffObjs({x:1,y:2}, {x:1,y:2}) ==> NULL
// diffObjs(my_array, my_array) ==> NULL
// diffObjs([1,'a'], [1,'1']) ==> NULL
// diffObjs(null, null) ==> NULL
// diffObjs(no_val, null) ==> NULL
//
// *Return copies of v1 and v2 on type mismatch*:
//
// When type of v1 and v2 are different or one is an array and the other
// is an object, the result array will contain exect copies of both
// v1 and v2.
//
// *Return minimal representation of differences among non-array objects*:
//
// Otherwise, when two objects are passed in, element 0
// in the result array contains the members and their values
// that exist in v1 but not v2, or members that exist in both
// v1 and v2 that have different values. Element 1 contains
// the same but with respect to v2, that is members and their
// values that exist in v2 but not v1, or members that exist in
// both v1 and v2 that have different values.
//
// Note: The members are represented in the result objects only when
// they are specific to the object of the corresponding value argument
// or when the members exist in both and have different values. The
// caller therefore can tell whether the object mismatch exists
// because of specificity of a member to one object vs. a mismatch
// in values where one is null and the other is not.
//
// Examples:
// diffObjs({a:10, b:"dog"}, {a:1, b:"dog"} ==> [ {a:10}, {a:1} ]
// diffObjs({a:10}, {a:10, b:"dog"} ==> [ {}, {b:"dog"} ]
// diffObjs({a:10, c:null}, {a:10, b:"dog"} ==> [ {c:null}, {b:"dog"} ]
// diffObjs({a:[1], b:"cat"},{a:1, b:"dog"} ==> [ {a:[1], b:"cat"}, {a:1, b:"dog"} ]
// diffObjs(
// {a:{ m1:"x", m2:"y"}, b:3 },
// {a:{ m1:"x", m2:"z", m3:1 }, b:3 } ) ==> [ {a:{m2:"y"}}, {a:{m2:"z",m3:1}} ]
//
// *Return copies of compared arrays when differing by position or value*
//
// If the two arguments arrays, the results in elements 0 and 1
// will contain results in array form that do not match with respect
// to both value and order. If two positionally corresponding
// elements in the array arguments have identical value (e.g., two
// scalars with matching values or two references to the same object),
// the corresponding values in the array will be null. The
// cardinality of the arrays within the result array will therefore
// always match that of the corresponding arguments.
//
// Examples:
// diffObjs([1,2], [1,2]) ==> [ [null,null], [null,null] ]
// diffObjs([1,2], [2,1]) ==> [ [1,2], [2,1] ]
// diffObjs([1,2], [1,2,3]) ==> [ [1,2,null], [2,1,3] ]
// diffObjs([1,1,2,3], [1,2,3]) ==> [ [null,1,2,3], [null,2,3] ]
//

var diffObjs = function(v1, v2) {

// return NULL when passed references to
// the same objects or matching scalar values
if (v1 === v2) {
return null;
}
var cloneIt = function(v) {
if (v == null || typeof v != 'object') {
return v;
}

var isArray = Array.isArray(v);

var obj = isArray ? [] : {};
if (!isArray) {
// handles function, etc
Object.assign({}, v);
}

for (var i in v) {
obj[i] = cloneIt(v[i]);
}

return obj;
}

// different types or array compared to non-array
if (typeof v1 != typeof v2 || Array.isArray(v1) != Array.isArray(v2)) {
return [cloneIt(v1), cloneIt(v2)];
}

// different scalars (no cloning needed)
if (typeof v1 != 'object' && v1 !== v2) {
return [v1, v2];
}

// one is null, the other isn't
// (if they were both null, the '===' comparison
// above would not have allowed us here)
if (v1 == null || v2 == null) {
return [cloneIt(v1), cloneIt(v2)];
}

// We have two objects or two arrays to compare.
var isArray = Array.isArray(v1);

var left = isArray ? [] : {};
var right = isArray ? [] : {};

for (var i in v1) {
if (!v2.hasOwnProperty(i)) {
left[i] = cloneIt(v1[i]);
} else {
var sub_diff = diffObjs(v1[i], v2[i]);
// copy the differences between the
// two objects into the results.
// - If the object is array, use 'null'
// to indicate the two corresponding elements
// match.
//
// - If the object is not an array, copy only
// the members that point to an unmatched
// object.
if (isArray || sub_diff) {
left[i] = sub_diff ? cloneIt(sub_diff[0]) : null;
right[i] = sub_diff ? cloneIt(sub_diff[1]) : null;
}
}
}

for (var i in v2) {
if (!v1.hasOwnProperty(i)) {
right[i] = cloneIt(v2[i]);
}
}

return [ left, right];
};

关于javascript - 获取两个javascript对象的增量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22108837/

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