Reputation: 157
I have 2 deep nested object of objects. 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?
Upvotes: 0
Views: 4265
Reputation: 30088
To solve this problem, we must:
source
object.reduce
callback function would first check if the source
value or it's other
value counter part are both objects. 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.reduce
function accepts a third argument which is used as the initial value for the accumulated of the reduce
function. We assign the third argument with key-values from the other
object that aren't found in the source
object. This is the simplest way to get the newly introduced values from the other
object towards the resulting object.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>
Upvotes: 2
Reputation: 6883
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
Note: you need to adjust the result based on your requirement in reduce. This result is made to match your output.
Upvotes: 0