0

I have two objects that look like:

{
    "data" : [ 
        {
            "name" : "toyota",
            "type" : "cars",
            "totals" : {
                "invalid" : 4,
                "valid" : 14,
                "percentage" : 77.78,
                "total" : 18
            }
        }
    ],
    "report_id": "123wa31a22aba05"
}

I would like to merge those two objects into one object with the following set of rules:

Every two cars that have the same name and type in the data should be merged. This means that totals will be:

"totals": {
    "invalid": "invalidA" + "invalidB"
    "valid": "validA" + "validB"
    "percentage" : calculatePercentage("invalid","valid")
    "total": "invalid" + "valid"
}

If there is only sub-object with some name and type, it will just push it as it to the merged report.

What I thought: Copy object one to result object. Then iterate over the second object and insert the elements into the result object (merge if needed). I would use the for loop as I'm used from Java, but it doesn't feel a good js code. What is the proper way to merge those two object in JS?

Example to make it easier:

Object 1:

{
    "data" : [ 
        {
            "name" : "toyota",
            "type" : "cars",
            "totals" : {
                "invalid" : 4,
                "valid" : 14,
                "percentage" : 77.78,
                "total" : 18
            }
        }
    ],
    "report_id": "123wa31a22aba05"
}

Object 2:

{
    "data" : [ 
        {
            "name" : "toyota",
            "type" : "cars",
            "totals" : {
                "invalid" : 2,
                "valid" : 5,
                "percentage" : 71.42,
                "total" : 7
            }
        }
    ],
    "report_id": "123wa31a22aba06"
}

Result:

{
    "data" : [ 
        {
            "name" : "toyota",
            "type" : "cars",
            "totals" : {
                "invalid" : 6,
                "valid" : 19,
                "percentage" : 76.0,
                "total" : 25
            }
        }
    ]
}
vesii
  • 2,760
  • 4
  • 25
  • 71
  • 2
    What have you tried, and what exactly is the problem with it? – jonrsharpe May 17 '20 at 11:06
  • @jonrsharpe Hi there. Thank you for replying. I used two basic `for` loop for the operation. It does not feel js style. My question is how to implement it in more of a js style (It feels like I'm writing java in js). – vesii May 17 '20 at 11:08
  • you can directly add dot notation in an object or use map function in an array – Nilesh Kant May 17 '20 at 11:09
  • 1
    If it works, so what? If there's a problem give a [mre], otherwise "feel js style" is opinion based. – jonrsharpe May 17 '20 at 11:09
  • @vesii, do this here `a` and `b` are two given objects: `Object.keys(a).forEach(k=>{ if(k=="data") { a[k] = a[k].reduce((acc, {name, type, ...rest})=>{ getArr2 = b.data.find(val=>val.name==name && val.type==type); if(getArr2){ rest.totals.invalid+=getArr2.totals.invalid; rest.totals.valid+=getArr2.totals.valid; rest.totals.total+=getArr2.totals.total; rest.totals.percentage=(rest.totals.valid/rest.totals.total)*100 } acc.push({name, type, ...rest}); return acc; },[])}})` – gorak May 17 '20 at 11:35

1 Answers1

0

This solution might help you.

var a = {
"data": [
    {
        "name": "toyota",
        "type": "cars",
        "totals": {
            "invalid": 4,
            "valid": 14,
            "percentage": 77.78,
            "total": 18
        }
    }
],
"report_id": "123wa31a22aba05"
},
b = {
    "data": [
        {
            "name": "toyota",
            "type": "cars",
            "totals": {
                "invalid": 2,
                "valid": 5,
                "percentage": 71.42,
                "total": 7
            }
        }
    ],
    "report_id": "123wa31a22aba06"
},

c = [...a.data, ...b.data];

var tmp = [];
for (let i = 0; i < c.length; i++) {
    for (let j = i + 1; j < c.length; j++) {
        if(c[i].name == c[j].name) {
            c[i].totals.invalid += c[j].totals.invalid;
            c[i].totals.valid += c[j].totals.valid;
            c[i].totals.total += c[j].totals.total;
            c[i].totals.percentage = (c[i].totals.valid / c[i].totals.total) * 100;
            c.splice(j, 1)
        }
    }    
}

console.log(c);
Kamal Kant
  • 1,031
  • 1
  • 12
  • 22