【问题标题】:how to group by nested properties using lodash?如何使用 lodash 按嵌套属性分组?
【发布时间】:2019-07-29 06:43:26
【问题描述】:

我有一个对象数组

{
    "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
        }
    ]
}

我需要将它们转换成

[{
    "_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
    }]
}]

我已经通过部分使用 lodash 和 vanilla js 完成了它,它完全可以正常工作。但可读性完全不好。我想单独使用 lodash 来实现这一点。有什么帮助吗?

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);

【问题讨论】:

    标签: javascript arrays typescript grouping lodash


    【解决方案1】:

    希望这就是您正在寻找的。​​p>

    1. 首先按employee_.id分组
    2. 然后映射每个组,获取第一个员工(因为每个组 必须有一个条目)
    3. 然后将每个组的所有其他成员(并取出外部部分)映射到work (除员工对象之外的所有内容)

    下面是一个例子:

    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>

    【讨论】:

      【解决方案2】:

      您可以创建一个使用 lodash 的 _.flow() 按员工 ID 分组的函数,然后使用工作数组创建一个员工对象:

      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>

      【讨论】:

      • 完美+1,谢谢
      • @OriDrori 尽量避免使用omit,而是将其余属性设为{employee, ...rest} 并使用rest
      【解决方案3】:

      您可以使用带有 Object.values()Array.reduce() 和解构分配的纯 JavaScript 简洁地做到这一点:

      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 = Object.values(data.work.reduce((acc, work) => {
        const { employee: { _id, ...rest }, ...job } = work;
        const jobs = (acc[_id] || {}).work || [];
        acc[_id] = { _id, ...rest, work: [...jobs, job] };
        return acc;
      }, {}));
      
      console.log(result);

      【讨论】:

      • 谢谢 +1 整洁,但我正在寻找 lodash 的答案,无论如何我会接受你的答案,如果我找不到任何与 lodash 相关的内容。
      • @Thamaraiselvam 不明白您为什么接受答案的 loadash 版本(我的和 Ori Drori 的答案)然后不接受。这个使用普通 JS 的答案看起来不错,然后你要求 lodash versoin(在这个 ans 的最后一条评论中),之后我想出了一些 lodash 解决方案(认为这可能对你有帮助)。不知道你到底在找什么。
      • @KoushikChatterjee 您在发布最佳答案方面做得非常出色。由于我使用的是 typescript ,因此您的答案存在一些语法问题,我很着急,所以我使用了 jo_va 答案。
      • @Thamaraiselvam 嗯,实际上这与我的答案或任何人的答案无关,如果您有任何问题,请评论您应该在那里评论的任何答案,以便为所有 SO 用户提供更大的图景可能会遇到这种问题。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-07-31
      • 1970-01-01
      • 1970-01-01
      • 2021-10-23
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多