Filtering through JS array of objets and adding the steps value where userName is same

Viewed 55

I am working with JavaScript. This might be relatively easier for professional developers. I want to loop through an array of objects and filter objects with the same userName and add their steps. Following response is the response from my API,

{
    "status": 1,
    "UserList": [
        {
            "_id": "5e8c04882e31eb0fa0f240dd",
            "userName": "devyansh",
            "starttime": 1586073600,
            "endtime": 1586077200,
            "steps": 1000,
            "createdTime": 1586234504,
            "__v": 0
        },
        {
            "status": "1",
            "_id": "5e8c04f82e31eb0fa0f240df",
            "userName": "devyansh",
            "starttime": 1586080800,
            "endtime": 1586084400,
            "steps": 47,
            "createdTime": 1586234616,
            "__v": 0
        },
        {
            "_id": "5e8c282e5040a21c1498d95b",
            "userName": "amit",
            "starttime": 1586170800,
            "endtime": 1586131200,
            "steps": 899,
            "createdTime": 1586243630,
            "__v": 0
        },
}

I need to filter through this UserList using userName, and add the steps if userName is found to be the same. Here is how I want the response to be,

{
   "status": 1,
   "finalList": [
    {
        "totalsteps": 1047,
        "list": [
            {
                "_id": "5e8c04882e31eb0fa0f240dd",
                "userName": "devyansh",
                "starttime": 1586073600,
                "endtime": 1586077200,
                "steps": 1000,
                "createdTime": 1586234504,
                "__v": 0
            },
            {
                "status": "1",
                "_id": "5e8c04f82e31eb0fa0f240df",
                "userName": "devyansh",
                "starttime": 1586080800,
                "endtime": 1586084400,
                "steps": 47,
                "createdTime": 1586234616,
                "__v": 0
            }
        ],
    },
    {
        "totalsteps": 899,
        "list": [
            "_id": "5e8c282e5040a21c1498d95b",
            "userName": "amit",
            "starttime": 1586170800,
            "endtime": 1586131200,
            "steps": 899,
            "createdTime": 1586243630,
            "__v": 0
          ],
    },
  ]
}

I already tried this, but not got the expected result,

var nameArray = []

  foundData.map((data) => {
     if (!nameArray.includes(data.userName)){
        nameArray.push(data.userName)
     }
  })
  console.log("nameArray",nameArray)
  var finalArray = nameArray.map((data1) => {
     return(  foundData.filter((data) => {
        return data1 === (data.userName)
        }))
     })
  console.log("finalArray",finalArray)

Thanks, in advance. Any help is much appreciated.

2 Answers

We can group array by userName and then sum up steps and push element of array inside of list. So it can be done through reduce method:

const result = obj.UserList.reduce((a, {userName, steps, ...rest})=> {
  a[userName] = a[userName] || {totalsteps: 0, list:[]};
  a[userName].totalsteps += steps;
  a[userName].list.push({userName, steps, ...rest});
  return a;
}, {})

console.log(Object.values(result));

An example:

let obj = {
    "status": 1,
    "UserList": [
        {
            "_id": "5e8c04882e31eb0fa0f240dd",
            "userName": "devyansh",
            "starttime": 1586073600,
            "endtime": 1586077200,
            "steps": 1000,
            "createdTime": 1586234504,
            "__v": 0
        },
        {
            "status": "1",
            "_id": "5e8c04f82e31eb0fa0f240df",
            "userName": "devyansh",
            "starttime": 1586080800,
            "endtime": 1586084400,
            "steps": 47,
            "createdTime": 1586234616,
            "__v": 0
        },
        {
            "_id": "5e8c282e5040a21c1498d95b",
            "userName": "amit",
            "starttime": 1586170800,
            "endtime": 1586131200,
            "steps": 899,
            "createdTime": 1586243630,
            "__v": 0
        }
      ]
};

const result = obj.UserList.reduce((a, {userName, steps, ...rest})=> {
  a[userName] = a[userName] || {totalsteps: 0, list:[]};
  a[userName].totalsteps += steps;
  a[userName].list.push({userName, steps, ...rest});
  return a;
}, {})

console.log(Object.values(result));

Go over UserList, Build an object with keys as "userName".
When userName already exist in object, just update the steps and list.
After the iteration, Get Object.values() of above object to get it as array.

const format = arr => {
  const res = {};
  arr.forEach(item => {
    if (!res[item.userName]) {
      res[item.userName] = {
        totalsteps: 0,
        list: []
      };
    }
    res[item.userName].totalsteps += item.steps;
    res[item.userName].list.push(item);
  });
  return Object.values(res);
};

const resp = {
  status: 1,
  UserList: [
    {
      _id: "5e8c04882e31eb0fa0f240dd",
      userName: "devyansh",
      starttime: 1586073600,
      endtime: 1586077200,
      steps: 1000,
      createdTime: 1586234504,
      __v: 0
    },
    {
      status: "1",
      _id: "5e8c04f82e31eb0fa0f240df",
      userName: "devyansh",
      starttime: 1586080800,
      endtime: 1586084400,
      steps: 47,
      createdTime: 1586234616,
      __v: 0
    },
    {
      _id: "5e8c282e5040a21c1498d95b",
      userName: "amit",
      starttime: 1586170800,
      endtime: 1586131200,
      steps: 899,
      createdTime: 1586243630,
      __v: 0
    }
  ]
};

const result = { status: resp.status, finalList: format(resp.UserList) };

console.log(result);

Related