如何链式调用lodash的groupBy与reduce按owner分组拼接id
问题描述
现有如下结构的数组:
const arr = [ {id: "id_0", owner: "owner_0", state: "accepted"}, {id: "id_1", owner: "owner_1", state: "denied"}, {id: "id_2", owner: "owner_1", state: "accepted"}, {id: "id_3", owner: "owner_1", state: "accepted"}, {id: "id_4", owner: "owner_2", state: "pending"}, ]
需求为将数据按owner字段分组,把每组内的id格式化为逗号分隔的字符串,无需返回state字段,期望输出结构如下:
const formattedArr = { owner_0: {ids: "id_0"}, owner_1: {ids: "id_1, id_2, id_3"}, owner_2: {ids: "id_4"} }
目前已尝试使用_.groupBy(arr, 'owner')完成分组,但不清楚如何结合回调、map或reduce方法格式化id并拼接为字符串,希望尽可能减少循环次数,初步实现思路为采用如下链式调用写法,求正确实现方案:
_.chain(arr) .groupBy('owner') .reduce(group => { //format the ids here return *formatted ids* }) .value()
实现方案
顺着已有的lodash链式调用逻辑补全即可。groupBy执行后会返回一个以owner值为键、对应分组元素数组为值的对象,后续用reduce遍历这个对象时,逐组提取id拼接成要求的字符串,组装成目标结构即可。整体仅需两次遍历(一次为groupBy内部的分组遍历,一次为reduce的分组处理遍历),已经是满足需求的最少循环次数:
const formattedArr = _.chain(arr) .groupBy('owner') .reduce((result, groupItems, ownerKey) => { // 提取当前分组下所有id,用逗号加空格拼接 result[ownerKey] = { ids: _.map(groupItems, 'id').join(', ') } return result }, {}) // 传入空对象作为reduce的初始累加值,也就是最终返回的结果载体 .value()
如果要进一步压缩循环次数,也可以不用额外的map方法,直接在分组内遍历拼接id:
const formattedArr = _.chain(arr) .groupBy('owner') .reduce((result, groupItems, ownerKey) => { result[ownerKey] = { ids: groupItems.reduce((idStr, item, idx) => { return idx === 0 ? item.id : `${idStr}, ${item.id}` }, '') } return result }, {}) .value()
原有链式写法跑不通的核心问题有两个:一是reduce没有传入空对象作为初始累加值,二是reduce的回调没有接收分组对应的owner键名参数,无法给结果对象设置对应属性。
内容的提问来源于stack exchange,提问作者natew
相关产品推荐
相关产品推荐

