Generic deep diff between two objects
I wrote a little class that is doing what you want, you can test it here.
Only thing that is different from your proposal is that I don't consider
[1,[{c: 1},2,3],{a:'hey'}]
and
[{a:'hey'},1,[3,{c: 1},2]]
to be same, because I think that arrays are not equal if order of their elements is not same. Of course this can be changed if needed. Also this code can be further enhanced to take function as argument that will be used to format diff object in arbitrary way based on passed primitive values (now this job is done by "compareValues" method).
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);
Deep comparison of two objects of same type but different structure
sorry got home pretty late, here's a typed version that works, posting as I've tested it
// pretty simple complicated as we're dealing with the same object type
type Accumulator<T> = { [k in keyof T]?: T[k] | {} }
// 1. just T =)
const deepCompare = <T extends object>(oldFilter: T, newFilter: T): Accumulator<T> => {
// 3. here though a different generic for varying props
const traverse = <O>(obj: O, filter: O, target: Accumulator<O> = {}): Accumulator<O> => {
for (let k in obj)
if (obj[k] instanceof Object && filter[k]) {
target[k] = {} // 4. O[k] for the next prop type
let targetResult = traverse<O[typeof k]>(obj[k], filter[k], target[k])
// delete empty entries if so desired
if (!Object.keys(targetResult).length)
delete target[k]
}
else if (obj[k] !== filter[k])
target[k] = obj[k] // store value
return target
}
// 2. still T on first recursion call
return traverse<T>(oldFilter, newFilter)
}
deepCompare({a: {v:'fv', g: 'ghdg', h: 'kfn', k: {l: '2222' }}},{a: {v:'fv', g: '1111', h: 'kfn', k: {l: 'dfg' }}})
that is all
JavaScript - Return differences between two Objects?
You can use Object.keys() and Array.includes() to do that.
var data = { "48": "{\"sid\":\"48\",\"name\":\"title 1\"}", "77": "{\"sid\":\"77\",\"name\":\"The blahblah title\"}", "83": "{\"sid\":\"83\",\"name\":\"The blahblah derp\"}", "87": "{\"sid\":\"87\",\"name\":\"The derpy title 4\"}"};
var obj1 = { "48": "{\"sid\":\"48\",\"name\":\"title 1\"}", "77": "{\"sid\":\"77\",\"name\":\"The blahblah title\"}"};
var result = {};var keys = Object.keys(obj1);
for (var key in data) { if (!keys.includes(key)) { result[key] = data[key]; }}
console.log(result);
JS Object compare and get diff only
You can recursively loop over the object and delete
the non-duplicate properties from the copy
object.
And if a property exists on the the original
object and not on the copy
, then add it into the copy
object. Following part of the code does that:
if (!copy.hasOwnProperty(k)) {
copy[k] = v;
}
function compare(original, copy) {
for (let [k, v] of Object.entries(original)) {
if (typeof v === "object" && v !== null) {
if (!copy.hasOwnProperty(k)) {
copy[k] = v;
} else {
compare(v, copy?.[k]);
}
} else {
if (Object.is(v, copy?.[k])) {
delete copy?.[k];
}
}
}
return copy;
}
const
original = { name: "John", id: "Doe", item: { drink: "coffee", money: 0, honey: 24 } },
copy = { name: "Alex", id: "Doe", item: { drink: "water", money: 0 } },
diff = compare(original, JSON.parse(JSON.stringify(copy)));
console.log(diff);
Comparing Objects and Pulling Out Deep Diff
You can use destructuring assignment
let {services:[,{history:[...data]}]} = obj2;
console.log(data.pop());
How to compare two objects in javascript and get difference?
The solutions is,
function Newdifference(origObj, newObj) {
function changes(newObj, origObj) {
let arrayIndexCounter = 0
return transform(newObj, function (result, value, key) {
if (value && !isObject(value) && !isEqual(JSON.stringify(value), JSON.stringify(origObj[key]))) {
let resultKey = isArray(origObj) ? arrayIndexCounter++ : key
result[resultKey] = (isObject(value) && isObject(origObj[key])) ? changes(value, origObj[key]) : value
}
});
};
return changes(newObj, origObj);
}
This function will return the changes which are traced in two objects
How compare two objects in javascript and create new object whose values are diffrent
I was not sure which value you wanted as an output for different keys, so I added both different values in an array... you can modify it based on your requirement.
Assumption: keys present in both objects are the same.
var obj1 = { name: 'jhon', age: '26', role: 'intern' };
var obj2 = { name: 'jhon berner', age: '26', role: 'intern' };
var newObj = {};
Object.keys(obj1).forEach((key) => {
if (obj1[key] !== obj2[key]) {
newObj[key] = [obj1[key], obj2[key]];
}
});
console.log(newObj);
Difference between two Objects - reduce
Please use this code
const find = Object.entries(objCombined).reduce((diff, [key]) => {
if (!obj2[key]) {
diff[key] = obj1[key];
return diff;
}
if (obj1[key] !== obj2[key]) diff[key] = obj2[key];
return diff;
}, {});
Related Topics
How to Render an Array of Objects in React
Get Global Variable Dynamically by Name String in JavaScript
Constructors in JavaScript Objects
Reactjs - Does Render Get Called Any Time "Setstate" Is Called
Passing Environment-Dependent Variables in Webpack
What's the Best Way to Convert a Number to a String in JavaScript
How to Add External Js Scripts to Vuejs Components
What Does = +_ Mean in JavaScript
How to Get Unique Values in an Array
Iframe Src Change Event Detection
Advantages of Createelement Over Innerhtml
Seedable JavaScript Random Number Generator
Maximum Size of an Array in JavaScript
Preserving a Reference to "This" in JavaScript Prototype Functions