JS如何按title字段分组重组对象数组 生成带rows属性的分组结构
现有代码错误点梳理
- 基础拼写错误:将数组长度属性
length错写为lenght,读取该属性时会得到undefined,初始条件判断链路从第一步就不符合预期。 - 方法误用:
Array.filter的设计用途是过滤数组合规项、返回新数组,不适合用来做分组查找逻辑。你在filter回调中编写push逻辑属于副作用操作:filter会遍历所有已存在的分组,只要当前遍历到的分组title和当前项key不相等,就会执行一次push新建分组的操作,这是分组重复出现的核心原因。举个例子:当已存在report分组、首次处理cv项时,遍历到report分组发现title不匹配,会立刻新建一个cv分组,完全不会做「全量检查是否已有对应分组」的判断。 - 数据写入错误:你写的
group.rows.push({single})会向数组中推入一个结构为{ single: 原对象 }的嵌套对象,不符合要求的「直接存储原对象」的结构规则。 - 判断逻辑无效:
grouped.length >=0是恒真条件——数组长度最小值为0,这个分支判断从设计上就永远不会走到假分支,你观察到的假分支执行属于filter回调反复触发push造成的错觉。
正确实现方案
使用Array.reduce实现分组的核心逻辑是:遍历每一项时,先检查累积的分组数组中是否已存在对应title的分组,存在则直接追加数据,不存在再新建分组。
const mynewdata = data.reduce((grouped, singleItem) => { const groupKey = singleItem.title; // 查找已存在的匹配分组 const targetGroup = grouped.find(group => group.title === groupKey); if (targetGroup) { // 匹配到分组直接追加原对象到rows targetGroup.rows.push(singleItem); } else { // 无匹配分组则新建分组推入累积数组 grouped.push({ title: groupKey, rows: [singleItem] }); } return grouped; }, []);
运行后输出结构完全符合需求:
[ { title: 'report', rows: [ { title: 'report', id: 17, uploadby: 'ramhari', filename: 'johnrepr', 'belongs to': 'johncena' }, { title: 'report', id: 17, 'upload-by': 'ram', filename: 'bincv', 'belongs to': 'binodkkhatri' } ] }, { title: 'cv', rows: [ { title: 'cv', id: 17, uploadby: 'ramhari', filename: 'alex', 'belongs to': 'alexharper' }, { title: 'cv', id: 17, uploadby: 'ramhari', filename: 'shyamcv', 'belongs to': 'shyamsundar' } ] }, { title: 'exam', rows: [ { title: 'exam', id: 17, 'upload-by': 'ram', filename: 'roha-nexam', 'belongs to': 'rohan' }, { title: 'exam', id: 17, uploadby: 'ganesh', filename: 'sandeshexam', 'belongs to': 'sandeshuprety' } ] } ]
注:你给出的目标结构示例中cv分组对应3条数据,实际原始数据中cv仅存在2条,上述输出和原始数据完全对应。
不要在filter、map这类遍历方法的回调中执行修改原数组长度的副作用操作,会导致遍历逻辑异常、出现重复或遗漏数据的问题。
内容的提问来源于stack exchange,提问作者alex
相关产品推荐
相关产品推荐

