简体   繁体   English

比较对象的两个深层嵌套对象,仅返回javascript / lodash中的差异

[英]Compare two deep nested object of objects and return only the differences in javascript / lodash

I have 2 deep nested object of objects. 我有2个对象的深层嵌套对象。 One is a "base" object and the other is a modified one. 一个是“基础”对象,另一个是经过修改的对象。

I essentially want to "delete" the base object from the modified object and return an object that only contains different data. 我本质上是想从修改后的对象中“删除”基础对象,并返回仅包含不同数据的对象。 Here is an example: 这是一个例子:

Base object: 基础对象:

baseObj : {
    image: {
        width: '100%',
        paddingTop: '0px',
        paddingRight: '0px',
        paddingBottom: '0px',
        paddingLeft: '0px'
    },
    wrap: {
        marginTop: '0px',
        marginRight: '0px',
        marginBottom: '0px',
        marginLeft: '0px'
    }
}

Object with modified data 具有修改数据的对象

mergedObject : {
    image: {
        width: '100%',  
        paddingTop: '0px',
        paddingRight: '24px', // modified value
        paddingBottom: '24px', // modified value
        paddingLeft: '0px'
    },
    wrap: {
        height: '100px', // new value
        marginTop: '24px', // modified value
        marginRight: '0px',
        marginBottom: '0px',
        marginLeft: '24px' // modified value
    }
}

I would like an object that is returned like this: 我想要这样返回的对象:

diffObject : {
    image: {
        paddingRight: '24px',
        paddingBottom: '24px',
    },
    wrap: {
        height: '100px',
        marginTop: '24px',
        marginLeft: '24px'
    }
}

The nesting could go a little deeper so it needs to be dynamic. 嵌套可能会更深一些,因此它必须是动态的。 Is there a way using lodash or some other library? 有没有办法使用lodash或其他一些库?

To solve this problem, we must: 为了解决这个问题,我们必须:

  • Create a function that traverses each node in the object recursively. 创建一个函数,该函数以递归方式遍历对象中的每个节点。 We can achieve this by using the reduce function when traversing the source object. 我们可以通过遍历source对象时使用reduce函数来实现此目的。
  • The reduce callback function would first check if the source value or it's other value counter part are both objects. reduce回调函数将首先检查source值或其other值计数器部分是否都是对象。 If they are, we'll use these values as arguments to recursively get the difference of both these objects. 如果它们是,我们将使用这些值作为参数来递归地获得这两个对象的差异。 Otherwise, if they are different, then we'll assign the resulting value from the other value. 否则,如果它们不同,那么我们将从other值中分配结果值。
  • Lastly, the reduce function accepts a third argument which is used as the initial value for the accumulated of the reduce function. 最后, reduce函数接受第三个参数,该参数用作reduce函数累加的初始值。 We assign the third argument with key-values from the other object that aren't found in the source object. 我们为第三个参数分配source对象中找不到的other对象的键值。 This is the simplest way to get the newly introduced values from the other object towards the resulting object. 这是从other对象向结果对象获取新引入值的最简单方法。

function differenceObjectDeep(source, other) {
  return _.reduce(source, function(result, value, key) {
    if (_.isObject(value) && _.isObject(other[key])) {
      result[key] = differenceObjectDeep(
        value,
        other[key]
      );
    } else if (!_.isEqual(value, other[key])) {
      result[key] = other[key];
    }
    return result;
  }, _.omit(other, _.keys(source)));
}

data.diffObject = differenceObjectDeep(
  data.baseObj,
  data.mergedObject
);

 var data = { baseObj: { image: { width: '100%', paddingTop: '0px', paddingRight: '0px', paddingBottom: '0px', paddingLeft: '0px' }, wrap: { marginTop: '0px', marginRight: '0px', marginBottom: '0px', marginLeft: '0px' } }, mergedObject: { image: { width: '100%', paddingTop: '0px', paddingRight: '24px', // modified value paddingBottom: '24px', // modified value paddingLeft: '0px' }, wrap: { height: '100px', // new value marginTop: '24px', // modified value marginRight: '0px', marginBottom: '0px', marginLeft: '24px' // modified value } } }; function differenceObjectDeep(source, other) { return _.reduce(source, function(result, value, key) { if (_.isObject(value) && _.isObject(other[key])) { result[key] = differenceObjectDeep( value, other[key] ); } else if (!_.isEqual(value, other[key])) { result[key] = other[key]; } return result; }, _.omit(other, _.keys(source))); } data.diffObject = differenceObjectDeep( data.baseObj, data.mergedObject ); console.log(data.diffObject); 
 body>div { min-height: 100%; top: 0; } 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.js"></script> 

you could use recursive function to find the last object. 您可以使用递归函数查找最后一个对象。

var checkIfObject = function(item){ //recursive function
_.each(item, function(v, k){
if(_.isObject(v)){
previousObject = k;
previousResult = v;
return checkIfObject(v);
}else{
    finalChildObjects[previousObject] = previousResult;
}
})
return finalChildObjects
}

/*Initialize Values for recursive function*/
var finalChildObjects = {};
var previousObject = '';
var previousResult = '';
baseObjectFinalTurn = checkIfObject(baseObj);
/*Initialize Values for recursive function*/
var finalChildObjects = {};
var previousObject = '';
var previousResult = '';
mergedObjectFinalTurn = checkIfObject(mergedObject);
console.clear();


var difference = {};
_.each(baseObjectFinalTurn, function(v, k){
    if(mergedObjectFinalTurn[k]){
    difference[k] = _.reduce(mergedObjectFinalTurn[k],function(result, value, key){
    if(baseObjectFinalTurn[k][key] != mergedObjectFinalTurn[k][key]){
    result[key] =  value;
    }

    return result
    }, {})

  }
  else{
  difference[k] = {};
  }
})

console.log(difference)

You can verify the result from this jsfiddle link 您可以从此jsfiddle链接验证结果

Note: you need to adjust the result based on your requirement in reduce. 注意:您需要根据reduce的要求调整结果。 This result is made to match your output. 该结果与您的输出相匹配。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM