不使用Lodash如何按对象键分组JavaScript对象数组?
对象数组按指定键分组的解决方案
你的现有代码其实已经完成了核心的分组逻辑,但返回的是以分组键值为属性名的对象(比如{ fruit: [...], meat: [...] }),和你期望的数组结构不符。只需要在现有逻辑基础上做一步格式转换就能得到目标结果。
修改后的完整代码
const grouper = key => array => // 先按原逻辑分组得到对象,再转成目标数组结构 Object.entries(array.reduce((acc, val) => { const property = val[key]; acc[property] = acc[property] || []; acc[property].push(val); return acc; }, {})).map(([type, foods]) => ({ type, foods }))
代码拆解说明
- reduce分组:和你原来的代码逻辑一样,把数组按指定的
key(这里是type)分组,得到一个键为分组值、值为对应元素数组的对象。 - Object.entries转换:把分组后的对象拆成键值对数组,比如变成
[ ['fruit', [苹果,香蕉]], ['meat', [鸟,牛]], ['drinks', [啤酒]] ]。 - map结构转换:把每个键值对映射成你需要的
{ type: 分组值, foods: 元素数组 }格式。
测试示例
代入你提供的foods数组测试:
const foods = [ {id: 1, title: 'apple', type: 'fruit'}, {id: 2, title: 'banana', type: 'fruit'}, {id: 3, title: 'bird', type: 'meat'}, {id: 4, title: 'beer', type: 'drinks'}, {id: 5, title: 'cow', type: 'meat'}, ] const groupByType = grouper('type') console.log(groupByType(foods))
输出结果完全匹配你期望的foodTypes格式。
可选:保证分组顺序(兼容老环境)
ES6+规范中普通对象会保留属性的插入顺序,但如果需要兼容更老的环境,或者要严格保证分组顺序和原数组中分组值首次出现的顺序一致,可以用Map代替普通对象存储分组结果:
const grouper = key => array => Array.from(array.reduce((acc, val) => { const property = val[key]; if (!acc.has(property)) { acc.set(property, []); } acc.get(property).push(val); return acc; }, new Map()).entries()).map(([type, foods]) => ({ type, foods }))
Map会严格按照键的插入顺序存储,兼容性更强。
内容的提问来源于stack exchange,提问作者Andrew
相关产品推荐
相关产品推荐

