0

I've got lodash to group my object by userId but I know want it group again by name values that are equal.

So for example I have the data:

"data": [
        {
            "name": "Red",
            "userId": "batman"
        },
        {
            "name": "Red",
            "userId": "batman"
        },
        {
            "name": "Blue",
            "userId": "batman"
        }
]

I'd like something that like:

[
  {userId: "Batman",
  name: {
   "red": 2
   "blue": 1
  }}
]

Basically to help me give a representation from which I can produce something like:

Red - 2 - batman
Blue - 1 - batman

I have this so far

console.log(
        chain(data)
            .groupBy("userId")
            .map((value, key) => ({ userId: key, name: value }))
            .value()
);

But this only gives me group by userId.

Any ideas/help would be appreciated.

Thanks

UPDATE - solved it by also needing a second function:

function filterArr(data: any, key: any){
        return data.reduce( (result: any, current: any) => {
            if(!result[current[key]]){
                result[current[key]] = 1;
            } else {
                result[current[key]] += 1;
            }
            return result;
        }, {})
    }

with:

console.log(
        chain(data)
            .groupBy("userId")
            .map((value, key) => ({ userId: key, name: filterArr(value, "name") }))
            .value()
);
userMod2
  • 8,312
  • 13
  • 63
  • 115

2 Answers2

1

I've made a solution to your question, based on the object structure that you requested

const _ = require("lodash");
const data = [
  {
    name: "Red",
    userId: "batman"
  },
  {
    name: "Red",
    userId: "batman"
  },
  {
    name: "Blue",
    userId: "batman"
  },
  {
    name: "Blue",
    userId: "gangam"
  }
];
let results = [];
const grouppedData = _.groupBy(data, "userId");

for (let userId in grouppedData) {
  const name = grouppedData[userId].reduce(
    (acc, val) => ({
      ...acc,
      [val.name]: acc[val.name] ? acc[val.name] + 1 : 1
  }),{});

  results.push({
    userId,
    name
  });
}

console.log(results);

I've made also a working sandbox here

Sabbin
  • 2,215
  • 1
  • 17
  • 34
0

You could use reduce method of array to get required output.

Please check below working code snippet :

const arr = [{"name":"Red","userId":"batman"},{"name":"Red","userId":"batman"},{"name":"Blue","userId":"batman"}];

let result = arr.reduce((r,{userId,name})=>{
   let rec = r.find(o => o.userId === userId);
    if(rec){
        rec.name[name] = (rec.name[name] || 0) + 1;
    }else{
        r.push({userId:userId,name:{[name]:1}});
    }
    return r;
},[]);

console.log(result);
Narendra Jadhav
  • 10,052
  • 15
  • 33
  • 44