Generic Deep Diff Between Two Objects

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



Leave a reply



Submit