如何使用lodash按嵌套属性进行分组?

4
我有一个对象数组。
{
    "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);
3个回答

3

希望这正是你要找的。

  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
完美+1,谢谢。 - Thamaraiselvam
@OriDrori 尽量避免使用 omit,而是将其余属性作为 {employee, ...rest} 并使用 rest - Koushik Chatterjee

1

您可以使用纯JavaScript简洁地完成此操作,使用 Object.values() Array.reduce()和解构赋值:

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
@Thamaraiselvam不明白为什么您接受了loadash版本的答案(我的和Ori Drori的答案),然后又取消了。这个使用普通JS的答案看起来很好,然后您要求lodash版本(在此答案的最后一条评论中),之后我提供了一些lodash解决方案(认为可能会对您有所帮助)。不知道您具体在寻找什么。 - Koushik Chatterjee
@KoushikChatterjee,你发布了最佳答案,做得真棒。由于我正在使用TypeScript,你的答案中有一些语法问题,而我又很匆忙,所以我使用了jo_va的答案。 - Thamaraiselvam
1
@Thamaraiselvam 嗯,实际上这不是关于我的答案或任何人的答案,如果您有任何问题,请在评论中提及任何答案,以便为所有可能遇到此类问题的 SO 用户提供更全面的信息。 - Koushik Chatterjee

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接