1

Below is my JSON object (Below is just example of values I am interested in , in reality along with cost there are many other paramters) I am trying to do this in experss js and using underscore

[
    {   
        "Cost":250,
        "author": { id :"2", name : "Joe" , workId: "5" }
    },
    {   
        "Cost":450,
        "author": { id :"2", name : "Joe" , workId: "6" }
    },
    {   
        "Cost":150,
        "author": { id :"3", name : "Tam" , workId: "7" }
    },
    {   
        "Cost":250,
        "author": { id :"2", name : "Joe" , workId: "8" }
    },
    {   
        "Cost":350,
        "author": { id :"3", name : "Tam" , workId: "9" }
    }
]

I want the output as below

Joe 950
Tam 500

I tried this:

var iw={};
iw = Object.keys(myJsonObject.reduce((iw, curr) => {
    //iw[curr.author.id] = iw[curr.author.id]
    iw[curr.author.id].cost += parseInt(curr.cost);
    return iw;
}, iw)).map(key => iw[key]);
console.log("New ::"+iw);

But I didn't get what I hoped for:

TypeError: Cannot read property 'cost' of undefined
    at Object.keys.myJsonObject.reduce (repl:3:7)
    at Array.reduce (<anonymous>)
New ::[object Object]
Julian
  • 4,176
  • 19
  • 40
Mizan
  • 450
  • 1
  • 5
  • 28
  • 1
    Stackoverflow is not a programming service. Please show an example of what you have tried. Also what language are you trying to accomplish this in? – Kevin Aug 20 '20 at 11:58
  • 1
    var iw={}; iw = Object.keys(myJsonObject.reduce((iw, curr) => { //iw[curr.author.id] = iw[curr.author.id] iw[curr.author.id].cost += parseInt(curr.cost); return iw; }, iw)).map(key => iw[key]); console.log("New ::"+iw); – Mizan Aug 20 '20 at 12:00
  • Hi @Kevin , I am using this in express js – Mizan Aug 20 '20 at 12:01
  • Possible duplicate of https://stackoverflow.com/questions/14446511/most-efficient-method-to-groupby-on-an-array-of-objects – Jack A. Aug 20 '20 at 21:25

2 Answers2

1

Probably a much cleaner way to do this, but a simple forEach would work. Obviously the output here is an object that contains the desired result.

const data = [
    {   
        "Cost":250,
        "author": { id :"2", name : "Joe" , workId: "5" }
    },
    {   
        "Cost":450,
        "author": { id :"2", name : "Joe" , workId: "6" }
    },
    {   
        "Cost":150,
        "author": { id :"3", name : "Tam" , workId: "7" }
    },
    {   
        "Cost":250,
        "author": { id :"2", name : "Joe" , workId: "8" }
    },
    {   
        "Cost":350,
        "author": { id :"3", name : "Tam" , workId: "9" }
    }
]

let a = {};

data.forEach(e => a[e.author.name] ? a[e.author.name] += e.Cost : a[e.author.name] = e.Cost);

console.log(a);
Fraser
  • 15,275
  • 8
  • 53
  • 104
1

as Fraser said

your original code had problem of not checking if that user already exists in the iw object already or not

your corrected solution:

myJsonObject = 
[
    {   
        "Cost":250,
        "author": { id :"2", name : "Joe" , workId: "5" }
    },
    {   
        "Cost":450,
        "author": { id :"2", name : "Joe" , workId: "6" }
    },
    {   
        "Cost":150,
        "author": { id :"3", name : "Tam" , workId: "7" }
    },
    {   
        "Cost":250,
        "author": { id :"2", name : "Joe" , workId: "8" }
    },
    {   
        "Cost":350,
        "author": { id :"3", name : "Tam" , workId: "9" }
    }
]

var iw={};
iw = myJsonObject.reduce((iw, curr) => {
iw[curr.author.name] ? iw[curr.author.name] += curr.Cost : iw[curr.author.name] = curr.Cost;
    return iw;
}, iw);

console.log(iw);

Result:

{Joe: 950, Tam: 500}
  • 1
    Also, the property was `Cost` with a uppercase C, not `cost` with a lowercase, and concatenating an object to a string gives you `[object Object]`, effectively hiding the information Mizan was interested in. – Julian Aug 20 '20 at 22:20
  • Thanks a ton , This works as expected . I was stuck on this for several hours. – Mizan Aug 21 '20 at 20:53