如何使用Lodash按对象数组的公共属性值分组生成数组对象?
使用Lodash对对象数组按公共属性值分组并完成聚合操作
当然可以!Lodash提供了非常顺手的工具来实现这个需求——不管是按属性的公共值分组,还是后续对分组后的FavouriteNo做求和、取最大值这类聚合操作,都能轻松搞定。下面我结合你给出的模拟数据场景一步步说明:
1. 先补全模拟数据
我先把你提到的模拟数组补全成更完整的样子,方便演示:
const arrayOfObj = [ { Name: "John-Code", FavouriteNo: 5, Team: "Frontend" }, { Name: "John-Design", FavouriteNo: 8, Team: "Frontend" }, { Name: "Mary-Code", FavouriteNo: 3, Team: "Backend" }, { Name: "Mary-Design", FavouriteNo: 7, Team: "Backend" }, { Name: "Bob-Code", FavouriteNo: 10, Team: "Frontend" } ];
这里我们可以选择按Team属性的公共值分组,或者如果需要按Name里的前缀(比如John、Mary)分组也可以,两种情况我都会演示。
2. 用Lodash分组
核心方法就是_.groupBy()——它会遍历你的对象数组,根据你指定的规则(可以是属性名,也可以是自定义函数)把对象分到对应的组里,最终生成一个以公共值为键、对应对象数组为值的结果。
情况1:按已有属性直接分组(比如Team)
直接把属性名传给_.groupBy()就行:
const groupedByTeam = _.groupBy(arrayOfObj, 'Team');
分组后的结果长这样:
{ "Frontend": [ { Name: "John-Code", FavouriteNo: 5, Team: "Frontend" }, { Name: "John-Design", FavouriteNo: 8, Team: "Frontend" }, { Name: "Bob-Code", FavouriteNo: 10, Team: "Frontend" } ], "Backend": [ { Name: "Mary-Code", FavouriteNo: 3, Team: "Backend" }, { Name: "Mary-Design", FavouriteNo: 7, Team: "Backend" } ] }
情况2:按属性的衍生值分组(比如Name的前缀)
如果需要按Name中-前面的部分(比如John、Mary)分组,就传一个自定义函数给_.groupBy():
const groupedByNamePrefix = _.groupBy(arrayOfObj, item => item.Name.split('-')[0]);
结果会是:
{ "John": [ { Name: "John-Code", FavouriteNo: 5, Team: "Frontend" }, { Name: "John-Design", FavouriteNo: 8, Team: "Frontend" } ], "Mary": [ { Name: "Mary-Code", FavouriteNo: 3, Team: "Backend" }, { Name: "Mary-Design", FavouriteNo: 7, Team: "Backend" } ], "Bob": [ { Name: "Bob-Code", FavouriteNo: 10, Team: "Frontend" } ] }
3. 分组后做聚合操作(求和、取最大值)
分组完成后,我们可以用_.mapValues()配合_.sumBy()、_.maxBy()这些方法,快速处理每组的FavouriteNo。
计算每组FavouriteNo的总和
const sumFavouriteByTeam = _.mapValues(groupedByTeam, group => _.sumBy(group, 'FavouriteNo'));
结果:
{ "Frontend": 23, "Backend": 10 }
找出每组FavouriteNo的最大值
const maxFavouriteByTeam = _.mapValues(groupedByTeam, group => _.maxBy(group, 'FavouriteNo').FavouriteNo);
结果:
{ "Frontend": 10, "Backend": 7 }
一次性获取多个聚合结果
如果你想同时得到每组的总和、最大值、数量甚至平均值,可以这样写:
const aggregatedResult = _.mapValues(groupedByTeam, group => ({ total: _.sumBy(group, 'FavouriteNo'), max: _.maxBy(group, 'FavouriteNo').FavouriteNo, memberCount: group.length, average: _.sumBy(group, 'FavouriteNo') / group.length }));
最终结果:
{ "Frontend": { total: 23, max: 10, memberCount: 3, average: 7.666... }, "Backend": { total: 10, max: 7, memberCount: 2, average: 5 } }
小提示
如果你的项目里没有引入Lodash,也可以用原生JS的Array.prototype.reduce()实现分组,但Lodash的方法更简洁易读,尤其是处理复杂分组和聚合逻辑的时候,代码会更清晰。
内容的提问来源于stack exchange,提问作者user8839735




