如何用Ramda按custodianCenter分组并统计value总和与数量
需求说明
需要将数组中按custodianCenter字段对对象分组,同时计算每组的value属性总和及元素数量。目前已通过Ramda的groupBy方法完成分组,但无法生成包含总和与数量的统计属性。
示例数据与当前代码
const data = [ {"_id":"+UJIRvYOSXysumiDdQTfkA==","arrival_date":"2022-01-10T00:00:00.000Z","attached_invoice":"invoice","attachment_photo_receipt":"photo receipt","code":"2432341-A","custodianCenter":"Pastagens","date_received":"2020-01-10T00:00:00.000Z","description":"Description Financial Input 1","expense_origin":2,"installment_entry":true,"installment_payment":null,"invoice_number":123,"nivel":"Fazenda","nivelData":["71b292ed-8441-4d1e-a19f-b39fdad55d9a"],"status":"input","status_payment":null,"value":234,"property":"Fertilizantes"}, {"_id":"XghoVK9uRke90xnsPZVjYw==","arrival_date":"2022-01-10T00:00:00.000Z","attached_invoice":"invoice","attachment_photo_receipt":"photo receipt","code":"2432341-A","comment":"Comentário 1","custodianCenter":"Pastagens","custodianCenterValue":22,"date_received":"2020-01-10T00:00:00.000Z","description":"Description Financial Input 1","expense_origin":2,"installment_entry":true,"installment_payment":null,"invoice_number":123,"nivel":null,"nivelData":["71b292ed-8441-4d1e-a19f-b39fdad55d9a"],"status":"input","status_payment":null,"value":234,"property":"Gratificações"}, {"_id":"mK+YXWeiTpGa3alAOENbvg==","arrival_date":"2022-01-10T00:00:00.000Z","attached_invoice":"invoice","attachment_photo_receipt":"photo receipt","code":"2432341-A","comment":"Comentário 1","custodianCenter":"Pastagens","custodianCenterValue":22,"date_received":"2020-01-10T00:00:00.000Z","description":"Description Financial Input 1","expense_origin":2,"installment_entry":true,"installment_payment":null,"invoice_number":123,"nivel":null,"nivelData":["71b292ed-8441-4d1e-a19f-b39fdad55d9a"],"property":null,"status":"input","status_payment":null,"value":234}, {"_id":"g7fVa41uRey+K+8OnKBO9g==","arrival_date":"2022-01-10T00:00:00.000Z","attached_invoice":"invoice","attachment_photo_receipt":"photo receipt","code":"2432341-A","comment":"Comentário 1","custodianCenter":"Pastagens","custodianCenterValue":22,"date_received":"2020-01-10T00:00:00.000Z","description":"Description Financial Input 1","expense_origin":2,"installment_entry":true,"installment_payment":null,"invoice_number":123,"nivel":null,"nivelData":["71b292ed-8441-4d1e-a19f-b39fdad55d9a"],"property":null,"status":"input","status_payment":null,"value":234}, {"_id":"GTZbvPnVQZ+7V4dfUjIT/w==","arrival_date":"2022-01-10T00:00:00.000Z","attached_invoice":"invoice","attachment_photo_receipt":"photo receipt","category":"Gratificações","code":"2432341-A","comment":"Comentário 1","custodianCenter":"Mão de Obra","custodianCenterValue":22,"date_received":"2020-01-10T00:00:00.000Z","description":"Description Financial Input 1","expense_origin":2,"installment_entry":true,"installment_payment":null,"invoice_number":123,"nivel":null,"nivelData":["71b292ed-8441-4d1e-a19f-b39fdad55d9a"],"status":"input","status_payment":null,"value":234} ] const res = R.compose( R.groupBy(R.prop("custodianCenter")) )(data)
期望结果
[ { custodianCenter: 'Pastagens', total: 936, quantity: 4 }, { custodianCenter: 'Mão de Obra', total: 234, quantity: 1 } ]
解决方案
通过Ramda的函数组合,在groupBy之后添加统计转换步骤即可实现需求:
- 用
R.toPairs将分组后的对象转为键值对数组(每个元素为[分组名称, 对应元素数组]) - 用
R.map遍历每个键值对,生成包含统计信息的对象:custodianCenter直接取键值对的第一个元素quantity取对应元素数组的长度total用R.sum结合R.pluck('value')计算数组中所有value的总和
完整代码(compose版)
const res = R.compose( R.map(([custodianCenter, items]) => ({ custodianCenter, quantity: items.length, total: R.sum(R.pluck('value', items)) })), R.toPairs, R.groupBy(R.prop("custodianCenter")) )(data)
更直观的pipe版
如果觉得compose的函数顺序反直觉,可以用R.pipe按执行顺序编写:
const res = R.pipe( R.groupBy(R.prop("custodianCenter")), R.toPairs, R.map(([custodianCenter, items]) => ({ custodianCenter, quantity: items.length, total: R.sum(R.pluck('value', items)) })) )(data)
执行上述代码后,会直接返回期望的数组格式,每个元素包含分组名称、元素数量和value总和。
内容的提问来源于stack exchange,提问作者Denis Alayza
相关产品推荐
相关产品推荐

