在树中深入查找对象,然后 return 对象及其通过树的路径
Deep find object in tree, then return object and the path to it through the tree
我已经编写了一个递归函数来查找给定对象和该树中的路径,但是当我将目标 id(在此处:if(tree.targetModuleId === 7))更改为 10 时我收到错误:
"message": "Uncaught TypeError: Cannot read properties of undefined (reading 'unshift')"
我应该得到路径:[1,2,5,6,10]。
最后我需要一个选项,无论我想得到一条路线的哪个点,我都需要得到路线是什么的答案,如果没有则得到 []
我很想获得有关该主题的帮助,附上我编写的代码。
let nodes = [
{ sourceModuleId: 1, targetModuleId: 2},
{ sourceModuleId: 1, targetModuleId: 8},
{ sourceModuleId: 2, targetModuleId: 3},
{ sourceModuleId: 2, targetModuleId: 5},
{ sourceModuleId: 8, targetModuleId: 9},
{ sourceModuleId: 3, targetModuleId: 7},
{ sourceModuleId: 5, targetModuleId: 6},
{ sourceModuleId: 6, targetModuleId: 10},
];
function toTree(arr) {
let arrMap = new Map(arr.map(item => [item.targetModuleId, item]));
let tree = [];
for (let i = 0; i < arr.length; i++) {
let item = arr[i];
if (item.sourceModuleId !==1) {
let parentItem = arrMap.get(item.sourceModuleId);
if (parentItem) {
let { children } = parentItem;
if (children) {
parentItem.children.push(item);
} else {
parentItem.children = [item];
}
}
} else {
tree.push(item);
}
}
return tree;
}
function findInTree(tree) {
if (tree.targetModuleId === 7) {
let path = [tree.sourceModuleId,tree.targetModuleId];
return {result: tree, path};
}
if(tree.children){
for(let i=0; i< tree.children.length;i++){
let tmp = findInTree(tree.children);
if (tmp) {
tmp.path.unshift(tree.sourceModuleId);
return tmp;
}
}
}
else {
for (let i = 0;i< tree.length; i++) {
let tmp = findInTree(tree[i]);
if (tmp) {
return tmp;
}
}
return [];
}
}
let tree = toTree(nodes);
let paths = findInTree(tree);
console.log(paths);
findInTree
中的一些问题:
return []
不正确:这是一个真值,因此调用者的 if (tmp)
将为真,但它不应该为真。你的函数returns的数据类型应该是一致的。它似乎应该是一个具有 result
和 path
属性的对象,但是在你的代码中有一个 return []
是不一致的。使 return null
,以指示没有这样的对象,并且根据调用者的预期行为,此值将是假的。将此 return null
移出 else
块,这样当 if
块不执行 return
.
时它也适用
在 if (tree.children)
块中,没有必要遍历这些子项,因为这将在递归调用中发生。请注意您从未在该循环中使用 i
,因此重复该主体是浪费时间。只需删除循环。
function findInTree(tree) {
if (tree.targetModuleId === 7) {
let path = [tree.sourceModuleId, tree.targetModuleId];
return {result: tree, path};
}
if (tree.children) {
// No need to loop. It will happen in the recursive call
let tmp = findInTree(tree.children);
if (tmp) {
tmp.path.unshift(tree.sourceModuleId);
return tmp;
}
}
else {
for (let i = 0;i< tree.length; i++) {
let tmp = findInTree(tree[i]);
if (tmp) {
return tmp;
}
}
}
return null; // data type consistency
}
我已经编写了一个递归函数来查找给定对象和该树中的路径,但是当我将目标 id(在此处:if(tree.targetModuleId === 7))更改为 10 时我收到错误:
"message": "Uncaught TypeError: Cannot read properties of undefined (reading 'unshift')"
我应该得到路径:[1,2,5,6,10]。
最后我需要一个选项,无论我想得到一条路线的哪个点,我都需要得到路线是什么的答案,如果没有则得到 []
我很想获得有关该主题的帮助,附上我编写的代码。
let nodes = [
{ sourceModuleId: 1, targetModuleId: 2},
{ sourceModuleId: 1, targetModuleId: 8},
{ sourceModuleId: 2, targetModuleId: 3},
{ sourceModuleId: 2, targetModuleId: 5},
{ sourceModuleId: 8, targetModuleId: 9},
{ sourceModuleId: 3, targetModuleId: 7},
{ sourceModuleId: 5, targetModuleId: 6},
{ sourceModuleId: 6, targetModuleId: 10},
];
function toTree(arr) {
let arrMap = new Map(arr.map(item => [item.targetModuleId, item]));
let tree = [];
for (let i = 0; i < arr.length; i++) {
let item = arr[i];
if (item.sourceModuleId !==1) {
let parentItem = arrMap.get(item.sourceModuleId);
if (parentItem) {
let { children } = parentItem;
if (children) {
parentItem.children.push(item);
} else {
parentItem.children = [item];
}
}
} else {
tree.push(item);
}
}
return tree;
}
function findInTree(tree) {
if (tree.targetModuleId === 7) {
let path = [tree.sourceModuleId,tree.targetModuleId];
return {result: tree, path};
}
if(tree.children){
for(let i=0; i< tree.children.length;i++){
let tmp = findInTree(tree.children);
if (tmp) {
tmp.path.unshift(tree.sourceModuleId);
return tmp;
}
}
}
else {
for (let i = 0;i< tree.length; i++) {
let tmp = findInTree(tree[i]);
if (tmp) {
return tmp;
}
}
return [];
}
}
let tree = toTree(nodes);
let paths = findInTree(tree);
console.log(paths);
findInTree
中的一些问题:
时它也适用return []
不正确:这是一个真值,因此调用者的if (tmp)
将为真,但它不应该为真。你的函数returns的数据类型应该是一致的。它似乎应该是一个具有result
和path
属性的对象,但是在你的代码中有一个return []
是不一致的。使return null
,以指示没有这样的对象,并且根据调用者的预期行为,此值将是假的。将此return null
移出else
块,这样当if
块不执行return
.在
if (tree.children)
块中,没有必要遍历这些子项,因为这将在递归调用中发生。请注意您从未在该循环中使用i
,因此重复该主体是浪费时间。只需删除循环。
function findInTree(tree) {
if (tree.targetModuleId === 7) {
let path = [tree.sourceModuleId, tree.targetModuleId];
return {result: tree, path};
}
if (tree.children) {
// No need to loop. It will happen in the recursive call
let tmp = findInTree(tree.children);
if (tmp) {
tmp.path.unshift(tree.sourceModuleId);
return tmp;
}
}
else {
for (let i = 0;i< tree.length; i++) {
let tmp = findInTree(tree[i]);
if (tmp) {
return tmp;
}
}
}
return null; // data type consistency
}