如何用JavaScript实现JSON数组按serviceType、policyProject两级分组
实现思路
现有代码仅完成serviceType维度的第一层分组,未对同一serviceType下同名policyProject做合并处理,导致每条原始数据都会生成独立的policyProject节点。可通过在reduce流程中增加临时索引的方式,快速匹配同组内的同名项目,实现两层嵌套分组的需求。
可运行的完整代码
let policyTree = [ {"serviceType": "pcf-sm","policyProject": "Policy_001","policy":"Nchf_001"}, {"serviceType": "pcf-sm", "policyProject": "Policy_001","policy":"PRA_001"}, {"serviceType": "pcf-sm", "policyProject" : "Policy_001","policy":"main"}, {"serviceType": "pcf-ue", "policyProject": "Policy_003", "policy":"ET_001"}, {"serviceType": "pcf-ue", "policyProject" : "abc", "policy": "main"} ] const groupedResult = Object.values( policyTree.reduce((acc, { serviceType, policyProject, policy }) => { // 初始化当前serviceType的分组结构 if (!acc[serviceType]) { acc[serviceType] = { // 最终输出的节点对象 node: { serviceType, policyProject: [] }, // 临时项目索引:以policyProject名称为key,关联对应节点的引用,实现O(1)查找 projectMap: {} } } const currentGroup = acc[serviceType] // 同组下不存在同名项目时,新建项目节点并存入索引表 if (!currentGroup.projectMap[policyProject]) { const projectNode = { name: policyProject, policies: [] } currentGroup.node.policyProject.push(projectNode) currentGroup.projectMap[policyProject] = projectNode } // 将当前policy值归集到对应项目的policies数组 currentGroup.projectMap[policyProject].policies.push(policy) return acc }, {}) // 提取最终需要的节点结构,移除临时索引 ).map(group => group.node) console.log(groupedResult)
关键逻辑说明
- 临时索引表的作用:避免每次合并时遍历整个
policyProject数组查找同名项目,数据量较大时查找效率更高。 - 合并规则校验:遍历每条原始数据时,先判断同serviceType下是否已有同名
policyProject节点,存在则直接追加policy值,不存在才新建节点,从根源上避免重复项目对象的生成。 - 顺序调整适配:如果需要和示例输出的
policies顺序完全一致(即main值排在项目数组的首位),可在policy值追加完成后增加排序逻辑:// 示例:让值为main的policy排在当前项目policies数组的首位 currentGroup.projectMap[policyProject].policies.sort((a, b) => { if (a === 'main') return -1 if (b === 'main') return 1 return 0 })
内容的提问来源于stack exchange,提问作者misbha afreen
相关产品推荐
相关产品推荐

