基于Id和ParentId重组嵌套数组并过滤无in_shop属性的节点
问题:将扁平数组转为嵌套结构并过滤无有效分支的项
需求说明
需要把扁平数组按parentFolderId构建嵌套层级结构,同时移除**自身及所有子级、子级的子级都不包含in_shop: true**的项。
输入示例
const menuItems = [ { id: 1, displayName: "Equipment", parentFolderId: null, // ... 其他属性 }, { id: 2, displayName: "Equipment", parentFolderId: 6, // ... 其他属性 }, { id: 3, displayName: "Equipment", parentFolderId: 2, in_shop: true // ... 其他属性 }, { id: 4, displayName: "Equipment", parentFolderId: 1, // ... 其他属性 }, { id: 5, displayName: "Equipment", parentFolderId: 1, // ... 其他属性 }, { id: 6, displayName: "Equipment", parentFolderId: null, // ... 其他属性 }, { id: 7, displayName: "Equipment", parentFolderId: 5, in_shop: true, // ... 其他属性 }, { id: 8, displayName: "Equipment", parentFolderId: 3, // ... 其他属性 }, // ... 更多对象 ];
期望输出
const menuItems = [ { id: 1, displayName: "Equipment", parentFolderId: null, // ... 其他属性 children: [ { id: 5, displayName: "Equipment", parentFolderId: 1, children: [ { id: 7, displayName: "Equipment", parentFolderId: 5, in_shop: true, // ... 其他属性 }, ] // ... 其他属性 }, ], }, { id: 6, displayName: "Equipment", parentFolderId: null, // ... 其他属性 children: [ { id: 2, displayName: "Equipment", parentFolderId: 6, // ... 其他属性 children: [ { id: 3, displayName: "Equipment", parentFolderId: 2, in_shop: true, // ... 其他属性 }, ], }, ], }, // ... 更多对象 ]
当前实现代码
已完成嵌套结构构建,但未实现过滤逻辑:
function addChild(obj) { // 获取子项并递归处理 let children = menuItems.filter(a => a.parentFolderId == obj.id).map(addChild) // 如果有子项则添加children属性 if (children.length > 0 ) { return { ...obj, children } } // 无子项则返回原对象 return { ...obj } } const result = menuItems.filter(a => a.parentFolderId == null).map(addChild)
解决方案
核心逻辑是自底向上判断分支是否保留:节点是否保留,取决于自身有in_shop: true,或者存在可保留的子分支。
修改后的代码如下:
function processItem(obj) { // 递归处理所有子项,过滤掉无效分支 const validChildren = menuItems .filter(item => item.parentFolderId === obj.id) .map(processItem) // 移除返回null的无效子节点 .filter(child => child !== null); // 判断当前节点是否需要保留:自身有in_shop,或者有有效子节点 const shouldKeep = obj.in_shop === true || validChildren.length > 0; if (!shouldKeep) { return null; // 不保留则返回null,上层会过滤掉 } // 有有效子节点则添加children属性,否则返回原对象 return validChildren.length > 0 ? { ...obj, children: validChildren } : { ...obj }; } const result = menuItems .filter(item => item.parentFolderId === null) .map(processItem) .filter(item => item !== null); // 过滤掉根节点中的无效项
代码说明
- 递归处理子项:先递归处理所有子节点,得到过滤后的有效子节点列表;
- 判断保留条件:当前节点自身有
in_shop: true,或者存在有效子节点,才会被保留; - 过滤无效节点:返回
null的节点会被上层的filter移除,最终只保留符合要求的分支。
比如示例中的id=4节点,自身无in_shop且没有有效子节点,会被过滤;id=1节点因为有id=5这个有效子分支,所以会被保留。
内容的提问来源于stack exchange,提问作者Latent-code
相关产品推荐
相关产品推荐

