对象与递归函数的比较
Objects comparison with recursive function
考虑以下函数的蓝图,该蓝图试图比较两个对象:
function objectCompare(a,b,path){
for (var prop in a) {
path=prop;
if (a.hasOwnProperty(prop) && !(b.hasOwnProperty(prop))) {
...
return false;
}
...
if (detectType(a[prop])==='Object'){
if (!objectCompare(a[prop],b[prop],path))
return false;
}
...
}
return true;
}
detectType
是我自己的函数,它检查变量的类型。我的问题是,每次进行递归调用时,我都希望丰富变量path
。然而,在递归调用完成的同时,path
必须遍历初始对象的剩余属性名,而不会被丰富。。。想象一下以下对象:
var Obj1 = {
p1: 's',
p2: {
p1: {a: { propA: 'a', propB: 'b' }},
p2: 'g',
}
};
var Obj2 = {
p1: 's',
p2: {
p1: {a: { propA: 'a', propB: 'c' }},
p2: 'g',
}
};
当函数objectCompare
返回时,我希望path
具有以下值:p2.p1.a.propB
,即使两个对象不同的点。我怎样才能做到这一点?
您必须将当前键添加到路径中,并将新路径传递给递归调用。考虑:
console.info=function(x){document.write('<pre>'+JSON.stringify(x,0,3)+'</pre>')}
//--
// compare: return path if a,b are different, null otherwise
function compare(a, b, path) {
var ta = typeof a,
tb = typeof b;
// different types - fail
if (ta !== tb) {
return path;
}
// scalars - null if equal, path if not
if (ta !== 'object') {
return a === b ? null : path;
}
// make a set of keys from both objects
var keys = Object.keys(a).concat(Object.keys(b)).filter(function(x, i, self) {
return self.indexOf(x) === i;
});
// for each key in set, compare values
var res = null;
keys.some(function(k) {
return res = compare(a[k], b[k], path.concat(k));
});
// return null or the first failed path
return res;
}
//
var Obj1 = {
p1: 's',
p2: {
p1: {a: { propA: 'a', propB: 'b' }},
p2: 'g',
}
};
var Obj2 = {
p1: 's',
p2: {
p1: {a: { propA: 'a', propB: 'c' }},
p2: 'g',
}
};
var res = compare(Obj1, Obj2, [])
console.info(res);
库deep-diff
可以满足您的需要。
上面的参考文献给出了这个示例代码:
var diff = require('deep-diff').diff;
var lhs = {
name: 'my object',
description: 'it''s an object!',
details: {
it: 'has',
an: 'array',
with: ['a', 'few', 'elements']
}
};
var rhs = {
name: 'updated object',
description: 'it''s an object!',
details: {
it: 'has',
an: 'array',
with: ['a', 'few', 'more', 'elements', { than: 'before' }]
}
};
var differences = diff(lhs, rhs);
上面的代码片段将产生以下描述差异的结构:
[ { kind: 'E',
path: [ 'name' ],
lhs: 'my object',
rhs: 'updated object' },
{ kind: 'E',
path: [ 'details', 'with', 2 ],
lhs: 'elements',
rhs: 'more' },
{ kind: 'A',
path: [ 'details', 'with' ],
index: 3,
item: { kind: 'N', rhs: 'elements' } },
{ kind: 'A',
path: [ 'details', 'with' ],
index: 4,
item: { kind: 'N', rhs: { than: 'before' } } } ]
值得注意的是,path
属性与您想要的输出非常相似。
相关文章:
- 递归函数中断
- 将jQuery对象传递到setTimeout递归函数中
- 对象与递归函数的比较
- 循环内部的递归函数未按预期工作
- 递归函数返回不正确
- 递归函数编程困境
- 给定一个带有数字的数组,我如何编写一个递归函数,当 2 个元素加起来为一个目标时,它会在数组中查找索引
- 返回不会退出 javascript 中的递归函数
- jquery递归函数转换为非递归函数
- AngularJS,promise带有递归函数
- 如何停止此递归函数
- 如何将下面的递归函数转换为纯函数
- jQuery setTimeout ajax递归函数在即时消息程序中短时间后抛出错误
- Javascript递归函数引用了这一点
- 如何将这个递归函数转换为迭代函数
- jQuery递归函数调用和Javascript之间有区别吗;s setInterval
- 从javascript中的递归函数获取undefined
- 将递归函数转换为异步 CPS 实现 (javascript)
- 我怎样才能把它变成一个循环,而不是一个递归函数
- 在Javascript的递归函数中使用正则表达式进行解析