javascript - 根据id递归获取树的段
问题描述
我正在尝试基于 id 获取树段。id 可能位于根目录,也可能位于子节点的任何位置。我的目标是获得整个家谱,而不是其他不相关的数据。
我有整个数据树和一个 ID。
这个想法是递归地执行此操作,因为孩子的数量是未知的。
import "./styles.css";
export default function App() {
const folderTree = [
{
id: "1-1",
children: [
{
id: "1-2",
parentId: "1-1",
children: []
}
]
},
{
id: "2-1",
children: [
{
id: "2-2",
parentId: "2-1",
children: [
{
id: "2-4",
parentId: "2-2",
children: []
}
]
},
{
id: "2-3",
parentId: "2-1",
children: []
}
]
}
];
const getRelatedTreeFolders = (folders, selectedFolderId) => {
//** goes top to bottom
const recursiveChildCheck = (folder, id) => {
// THIS trial failed
// let foundNested = false;
// if (folder.id === id) {
// return true;
// }
// function recurse(folder) {
// if (!folder.hasOwnProperty("children") || folder.children.length === 0)
// return;
// for (var i = 0; i < folder.children.length; i++) {
// if (folder.children[i].id === id) {
// foundNested = true;
// break;
// } else {
// if (folder.children[i].children.length > 0) {
// recurse(folder.children[i].children);
// if (foundNested) {
// break;
// }
// }
// }
// }
// }
// recurse(folder);
// return foundNested;
const aChildHasIt =
folder.children.length > 0 && folder.children.some((f) => f.id === id);
if (aChildHasIt) return true;
let nestedChildHasIt = false;
/** The problem seems to be here */
folder.children.forEach((childFolder) => {
// Is using a forEach loop the correct way?
// ideally it seems there is a simple way to do a recursive .some on the dhildren...
childFolder.children.length>0 && recursiveChildCheck(childFolder, id)
});
if (nestedChildHasIt) return true;
folder.children && folder.children.forEach(recursiveChildCheck);
};
const treeSegment = folders.reduce((result = [], folder) => {
if (
folder.id === selectedFolderId ||
recursiveChildCheck(folder, selectedFolderId)
) {
result.push(folder);
}
return result;
}, []);
return treeSegment;
};
const selectedFolderId = "2-1";
const selectedFolderId1 = "2-2";
const selectedFolderId2 = "2-4";
const selectedFolderId3 = "2-3";
const selectedFolderId4 = "3-1";
const selectedFolderId5 = "1-1";
const selectedFolderId6 = "1-2";
console.log("parent");
console.log(getRelatedTreeFolders(folderTree, selectedFolderId));
console.log("child");
console.log(getRelatedTreeFolders(folderTree, selectedFolderId1));
console.log("grandchild"); // this fails
console.log(getRelatedTreeFolders(folderTree, selectedFolderId2));
console.log("sibling");
console.log(getRelatedTreeFolders(folderTree, selectedFolderId3));
console.log("not found");
console.log(getRelatedTreeFolders(folderTree, selectedFolderId4));
console.log("other parent");
console.log(getRelatedTreeFolders(folderTree, selectedFolderId5));
console.log("other child");
console.log(getRelatedTreeFolders(folderTree, selectedFolderId6));
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
{/* <h2>{JSON.stringify(result)}</h2> */}
</div>
);
}
解决方案
一些问题:
recursiveChildCheck
应该返回一个布尔值,但在某些情况下不undefined
返回 ( ),因为return
以下表达式中缺少一条语句:folder.children && folder.children.forEach(recursiveChildCheck);
此外,在上面的表达式中,运算符的第二个操作数
&&
永远不会被计算,因为folder.children
它是一个数组,并且数组总是真值,即使是空数组。为了给第二个操作数一个机会,第一个操作数应该是folder.children.length > 0
但即使进行了更正,第二个操作数也将始终计算为
undefined
,因为这是.forEach
设计返回的结果。您应该在那里有一个返回布尔值的方法调用,例如some
.nestedChildHasIt
初始化后永远不会获得任何其他值,因此return true
将永远不会发生以下情况:if (nestedChildHasIt) return true;
您可能打算
nestedChildHasIt
在前面的forEach
循环中设置为 true,但似乎您在这里有另一种方法来执行与最后的另一个forEach
循环相同的操作。
我认为您一直在努力解决的问题是您既需要检查布尔条件(子树是否有id
?),并且您需要将子树过滤到正确的子节点,创建一个具有此的新节点独特的孩子。
更正的代码:
function getForestSegment(nodes, id) {
function recur(nodes) {
for (const node of nodes) {
if (node.id === id) return [node];
const children = recur(node.children);
if (children.length) return [{ ...node, children}];
}
return [];
}
return recur(nodes);
}
// Example from question:
const forest = [{id: "1-1",children: [{id: "1-2",parentId: "1-1",children: []}]},{id: "2-1",children: [{id: "2-2",parentId: "2-1",children: [{id: "2-4",parentId: "2-2",children: []}]},{id: "2-3",parentId: "2-1",children: []}]}];
for (const id of ["2-1", "2-2", "2-4", "2-3", "3-1", "1-1", "1-2"]) {
console.log(id);
console.log(getForestSegment(forest, id));
}
推荐阅读
- r - Groupby多列并计算R中的年度和每月百分比变化
- python - 查找回文数的 Python 代码
- c++ - RSA使用C中的openssl库使用给定的私钥字符串解密消息
- bash - 如何使用 shell 脚本过滤按小时运行的 docker 容器?
- python - 方法返回“NoneType”对象
- jenkins - Kubernetes 上的 Jenkins - 权限被拒绝
- vue.js - 未捕获的类型错误:无法读取未定义的属性“使用”
- php - 使用 php 从子目录中获取 azure blob 文件
- javascript - Vue 3 和 Typescript - 无法访问方法中的数据属性
- sql-server - 扩展事件中的死锁图未显示