如何实现递归获取匹配项目的所有嵌套父级项目的算法
如何实现递归获取匹配项目的所有嵌套父级项目的算法
看起来你已经迈出了第一步,但目前的代码只能拿到目标项的直接父级,没法递归获取所有嵌套的父项对吧?我来帮你完善这个逻辑,让它能完整收集从目标项到最顶层父项的整个层级链。
首先先梳理下核心需求:
- 第一步:找到
name严格等于searchValue的目标项目 - 第二步:递归向上查找该项目的
programParent,直到父项的programParent为空字符串 - 最终结果要包含目标项本身以及所有层级的父项(和你给出的
expected顺序一致)
优化思路与完整实现
为了让查找父项的效率更高,我们可以先把数组转换成以id为键的映射对象,这样每次查找父项都能直接通过id获取,不用遍历整个数组;然后通过循环(或者递归)来逐层向上收集父项:
const programs = [ { id: '23', name: 'ventas', programParent: '' }, { id: '24', name: 'ventas OUT Personal', programParent: '23' }, { id: '25', name: 'ventas OUT Personal plus', programParent: '24' }, { id: '26', name: 'ventas IN Hogares', programParent: '23' }, { id: '27', name: 'Ad Hoc', programParent: '' }, { id: '28', name: 'Ad Hoc asd', programParent: '27' }, { id: '29', name: 'Ad Hoc 123', programParent: '27' }, { id: '30', name: 'ventas IN Personal plus', programParent: '26' }, ]; const searchValue = 'ventas OUT Personal plus'; // 1. 找到匹配的目标项目(假设name唯一,用find;如果有多个匹配项,改用filter遍历处理) const targetProgram = programs.find(p => p.name === searchValue); if (!targetProgram) { console.log('未找到匹配的项目'); // 没有匹配项时的自定义处理逻辑 } // 2. 将programs数组转换为以id为键的映射,提升查找效率 const programById = programs.reduce((map, program) => { map[program.id] = program; return map; }, {}); // 3. 循环收集层级链(用循环避免递归层级过深导致栈溢出,层级少的话递归也可以) function getFullHierarchy(target, programMap) { const hierarchy = []; let currentProgram = target; while (currentProgram) { // 将当前项目加入结果 hierarchy.push(currentProgram); // 获取父项id,若为空则停止循环 const parentId = currentProgram.programParent; currentProgram = parentId ? programMap[parentId] : null; } return hierarchy; } // 4. 调用函数得到结果 const result = getFullHierarchy(targetProgram, programById); console.log(result); // 输出结果和你给出的expected完全一致
代码细节说明
- 映射对象的作用:
programById把每个项目的id作为键,项目本身作为值,这样查找父项时只需要programById[parentId],时间复杂度从O(n)降到O(1),数据量大的时候优势很明显。 - 循环 vs 递归:这里用循环是因为如果层级特别深(比如几十层),递归可能会触发栈溢出;如果你的场景层级比较浅,也可以改成递归实现,逻辑更简洁:
// 递归版本的层级收集函数 function getFullHierarchyRecursive(target, programMap) { if (!target) return []; return [target, ...getFullHierarchyRecursive(programMap[target.programParent], programMap)]; }
- 边界处理:加入了
if (!targetProgram)的判断,避免找不到匹配项时后续代码报错,实际项目中可以根据需求添加对应的错误提示或处理逻辑。
对比你原来的代码
你原来的代码只遍历了一次数组,找到目标项的直接父项就停止了,没有继续向上查找父项的父项,所以只能得到一个父项;而上面的实现会逐层向上遍历,直到找到最顶层的父项(programParent为空)为止。
备注:内容来源于stack exchange,提问作者sonEtLumiere
相关产品推荐
相关产品推荐

