'How can I compare 2 nested objects, subtracting the differences & returning the equals?
I have the below 2 variables.
const val1 = {
students: {
grade: [
{
subject: "Math3",
name: "jack",
mark: 60,
attendance: 90,
abscent: 2,
},
],
class: [
{
className: "math3",
students: 50,
absenteeism: 10,
requirment: [
{
subject: "math1",
mark: 60,
pass: 51,
},
{
subject: "math2",
mark: 60,
pass: 51,
},
],
},
],
},
};
const val2 = {
students: {
grade: [
{
subject: "Math3",
name: "jack",
mark: 80
},
],
class: [
{
className: "math3",
students: 40,
absenteeism: 10,
requirment: [
{
subject: "math1",
mark: 75,
pass: 51,
},
{
subject: "math2",
mark: 90,
pass: 51,
},
],
},
],
},
};
I am trying to get the below result by returning the the key and value if they are the same, & if the key is a number, return the difference of that number & if the item doesn't exist, skip. Like so.
students: {
grade: [
{
subject: "Math3",
name: "jack",
diff: 20
},
],
class: [
{
className: "math3",
diff: 10,
requirment: [
{
subject: "math1",
diff: 15,
},
{
subject: "math2",
diff: 30,
},
],
},
],
},
};
Code so far. I get the values but not the way i want it. Also, is there a more cleaner way.
const changeTable = (table1, table2) => {
const result = {};
result["students"] = {};
let file1= table1.students
let file2=table2.students
for (let x in file1) {
if (file2[x]) {
result.students[x] =file1[x]
.map((y) => file2[x]
.map((z)=> Object.keys(y)
.map((key)=> {
if (y[key] === z[key]) {
return {[key]:y[key]}
}
if (y[key] !== z[key]) {
if (typeof y[key] === "number") {
const res= Number(z[key])-Number(y[key])
if (!isNaN(res)) {
return {[key]:res}
}
}
}
}
).filter(i =>i)))
}
}
return result
};
changeTable(val1, val2)
Any advice is much appreciated.
Solution 1:[1]
I tried to match your expected output as closely as possible. In general terms, this is not a task suitable for array methods like map
because what you really need here is recursive traversal of objects. I added comments to the code to show what it's doing, in case something is not quite right.
const val1 = {
"students": {
"grade": [
{
"subject": "Math3",
"name": "jack",
"mark": 60,
"attendance": 90,
"abscent": 2
}
],
"class": [
{
"className": "math3",
"students": 50,
"absenteeism": 10,
"requirment": [
{
"subject": "math1",
"mark": 60,
"pass": 51
},
{
"subject": "math2",
"mark": 60,
"pass": 51
}
]
}
]
}
}
const val2 = {
"students": {
"grade": [
{
"subject": "Math3",
"name": "jack",
"mark": 80
}
],
"class": [
{
"className": "math3",
"students": 40,
"absenteeism": 10,
"requirment": [
{
"subject": "math1",
"mark": 75,
"pass": 51
},
{
"subject": "math2",
"mark": 90,
"pass": 51
}
]
}
]
}
}
function diffObject(obj1, obj2) {
let result = {}
for (let key in obj1) {
// ignore properties not present in both objects
if (!(key in obj2)) continue
// ignore not same type, such as a number and string
if (typeof obj1[key] !== typeof obj2[key]) continue
// when both are number, set the property to the difference of the two
if (typeof obj1[key] === 'number') {
// only use different numbers
if (obj1[key] !== obj2[key]) {
result[key] = obj2[key] - obj1[key]
// in case you really wanted the "diff" property
// result.diff = obj2[key] - obj1[key]
}
}
// recursively iterate over each member of array
else if (Array.isArray(obj1[key]) && Array.isArray(obj2[key])) {
result[key] = obj1[key].map((item, index) => diffObject(item, obj2[key][index]))
}
// recursively iterate objects
else if (typeof obj1[key] === 'object' && obj1[key]) {
result[key] = diffObject(obj1[key], obj2[key])
}
// copy equal data
else if (obj1[key] === obj2[key]) {
result[key] = obj1[key]
}
// anything else is ignored
}
return result
}
console.log(diffObject(val1, val2))
There are edge cases that this cannot solve, such as recursive structures or non-plain objects.
Also, in your desired output, you keep using diff
property, but in some cases, the objects have two numeric properties, so it would be overriden, I kept the original property name instead.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Jakub Kotrs |