Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to group by nested properties using lodash?

I have array of objects

{
    "work": [{
            "_id": "5c80c5c00c253823fc443337",
            "start": "2019-01-01T18:30:00.000Z",
            "end": "2019-01-02T18:30:00.000Z",
            "employee": {
                "_id": "5c80c16e0c253823fc44332a",
                "status": "active",
                "location": "Chennai",
                "contact_number": "1234567890"
            },
            "allocation": 30
        },
        {
            "_id": "5c80c5ef0c253823fc443339",
            "start": "2018-12-31T18:30:00.000Z",
            "end": "2019-09-30T18:30:00.000Z",
            "employee": {
                "_id": "5c80c16e0c253823fc44332a",
                "status": "active",
                "location": "Chennai",
                "contact_number": "1234567890"
            },
            "allocation": 100
        },
        {
            "_id": "5c80c60b0c253823fc44333a",
            "start": "2018-12-31T18:30:00.000Z",
            "end": "2020-10-07T18:30:00.000Z",
            "employee": {
                "_id": "5c80c16e0c253823fc44332a",
                "status": "active",
                "location": "Chennai",
                "contact_number": "1234567890"
            },
            "allocation": 25
        },
        {
            "_id": "5c80c65e0c253823fc44333b",
            "start": "2019-01-01T18:30:00.000Z",
            "end": "2019-10-04T18:30:00.000Z",
            "employee": {
                "_id": "5c80c1940c253823fc44332b",
                "status": "active",
                "location": "Chennai",
                "contact_number": "1234567890"
            },
            "allocation": 50
        },
        {
            "_id": "5c80c7240c253823fc44333f",
            "start": "2018-12-31T18:30:00.000Z",
            "end": "2019-10-09T18:30:00.000Z",
            "employee": {
                "_id": "5c80c26e0c253823fc44332e",
                "status": "active",
                "location": "Chennai",
                "contact_number": "1234567890"
            },
            "allocation": 25
        }
    ]
}

I need to convert them into

[{
    "_id": "5c80c16e0c253823fc44332a",
    "status": "active",
    "location": "Chennai",
    "contact_number": "1234567890",
    "work": [{
        "_id": "5c80c5c00c253823fc443337",
        "start": "2019-01-01T18:30:00.000Z",
        "end": "2019-01-02T18:30:00.000Z",
        "allocation": 30
    }, {
        "_id": "5c80c5ef0c253823fc443339",
        "start": "2018-12-31T18:30:00.000Z",
        "end": "2019-09-30T18:30:00.000Z",
        "allocation": 100
    }, {
        "_id": "5c80c60b0c253823fc44333a",
        "start": "2018-12-31T18:30:00.000Z",
        "end": "2020-10-07T18:30:00.000Z",
        "allocation": 25
    }]
}, {
    "_id": "5c80c1940c253823fc44332b",
    "status": "active",
    "location": "Chennai",
    "contact_number": "1234567890",
    "work": [{
        "_id": "5c80c65e0c253823fc44333b",
        "start": "2019-01-01T18:30:00.000Z",
        "end": "2019-10-04T18:30:00.000Z",
        "allocation": 50
    }]
}, {
    "_id": "5c80c26e0c253823fc44332e",
    "status": "active",
    "location": "Chennai",
    "contact_number": "1234567890",
    "work": [{
        "_id": "5c80c7240c253823fc44333f",
        "start": "2018-12-31T18:30:00.000Z",
        "end": "2019-10-09T18:30:00.000Z",
        "allocation": 25
    }]
}]

I have done it by partially using lodash and vanilla js and it works completely fine. but readability wise is completely bad. I want to achieve this using just lodash alone. Any help?

let ids: any = groupBy(this.project.work, function (res) {
    return res.employee._id;
});

for (let id in ids) {
    let tmp = [];
    let employee_added = false;
    ids[id].map((work) => {
        if (!employee_added) {
            tmp = work.employee;
            tmp['work'] = [];
            employee_added = true;
        }
        delete work.employee;
        tmp['work'].push(work);
    })

    this.employees.push(tmp);
}

console.log(this.employees);
like image 755
Thamaraiselvam Avatar asked Oct 24 '25 04:10

Thamaraiselvam


2 Answers

Hopefully, this is what you are looking for.

  1. First group it by employee_.id
  2. Then map each group, take employee of first one (since every group must have one entry)
  3. Then map all other members (and take outer part) of each group to work (everything apart from employee object)

Here is the example below:

let works = [{"_id":"5c80c5c00c253823fc443337","start":"2019-01-01T18:30:00.000Z","end":"2019-01-02T18:30:00.000Z","employee":{"_id":"5c80c16e0c253823fc44332a","status":"active","location":"Chennai","contact_number":"1234567890"},"allocation":30},{"_id":"5c80c5ef0c253823fc443339","start":"2018-12-31T18:30:00.000Z","end":"2019-09-30T18:30:00.000Z","employee":{"_id":"5c80c16e0c253823fc44332a","status":"active","location":"Chennai","contact_number":"1234567890"},"allocation":100},{"_id":"5c80c60b0c253823fc44333a","start":"2018-12-31T18:30:00.000Z","end":"2020-10-07T18:30:00.000Z","employee":{"_id":"5c80c16e0c253823fc44332a","status":"active","location":"Chennai","contact_number":"1234567890"},"allocation":25},{"_id":"5c80c65e0c253823fc44333b","start":"2019-01-01T18:30:00.000Z","end":"2019-10-04T18:30:00.000Z","employee":{"_id":"5c80c1940c253823fc44332b","status":"active","location":"Chennai","contact_number":"1234567890"},"allocation":50},{"_id":"5c80c7240c253823fc44333f","start":"2018-12-31T18:30:00.000Z","end":"2019-10-09T18:30:00.000Z","employee":{"_id":"5c80c26e0c253823fc44332e","status":"active","location":"Chennai","contact_number":"1234567890"},"allocation":25}]


let res = _(works)
            .groupBy('employee._id')
            .map(g => ({...g[0].employee, work: _.map(g, ({employee, ...rest}) => ({...rest}))}))
            .value();
            
console.log(res)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>
like image 84
Koushik Chatterjee Avatar answered Oct 26 '25 16:10

Koushik Chatterjee


You can create a function that uses lodash's _.flow() that groups by the employee id, and then creates an employee object with work array:

const { flow, partialRight: pr, groupBy, map, head, get, omit } = _

const fn = flow(
  pr(groupBy, 'employee._id'),
  pr(map, group => ({ // create the employee objects
    ...get(head(group), 'employee'), // get the employee data and spread it
    work: group.map(o => omit(o, 'employee')) // create the work array by removing the employee from each work object
  }))
)

const data = {"work":[{"_id":"5c80c5c00c253823fc443337","start":"2019-01-01T18:30:00.000Z","end":"2019-01-02T18:30:00.000Z","employee":{"_id":"5c80c16e0c253823fc44332a","status":"active","location":"Chennai","contact_number":"1234567890"},"allocation":30},{"_id":"5c80c5ef0c253823fc443339","start":"2018-12-31T18:30:00.000Z","end":"2019-09-30T18:30:00.000Z","employee":{"_id":"5c80c16e0c253823fc44332a","status":"active","location":"Chennai","contact_number":"1234567890"},"allocation":100},{"_id":"5c80c60b0c253823fc44333a","start":"2018-12-31T18:30:00.000Z","end":"2020-10-07T18:30:00.000Z","employee":{"_id":"5c80c16e0c253823fc44332a","status":"active","location":"Chennai","contact_number":"1234567890"},"allocation":25},{"_id":"5c80c65e0c253823fc44333b","start":"2019-01-01T18:30:00.000Z","end":"2019-10-04T18:30:00.000Z","employee":{"_id":"5c80c1940c253823fc44332b","status":"active","location":"Chennai","contact_number":"1234567890"},"allocation":50},{"_id":"5c80c7240c253823fc44333f","start":"2018-12-31T18:30:00.000Z","end":"2019-10-09T18:30:00.000Z","employee":{"_id":"5c80c26e0c253823fc44332e","status":"active","location":"Chennai","contact_number":"1234567890"},"allocation":25}]}

const result = fn(data.work)

console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.js"></script>
like image 20
Ori Drori Avatar answered Oct 26 '25 16:10

Ori Drori