Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/439.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 在根对象和任何对象之间的对象树中查找对象_Javascript_Typescript_Recursion_Tree - Fatal编程技术网

Javascript 在根对象和任何对象之间的对象树中查找对象

Javascript 在根对象和任何对象之间的对象树中查找对象,javascript,typescript,recursion,tree,Javascript,Typescript,Recursion,Tree,我有一个典型的树状数据结构,如下所示: [ { data: object, subs: [ ...other objects... ] }, ...other objects... ] 它可以有任何形状和数量的节点 我编写了一个方法,该方法应该递归地查找并返回根r和给定对象o之间的路径(一个中间对象数组)。(无论是否包括r和o我都不在乎) 公共getPath(树:数组,o:object):数组{ let路径:数组=[]; 函数f(子树:数组):void{

我有一个典型的树状数据结构,如下所示:

[
  {
    data: object,
    subs:
      [ ...other objects... ]
  },
  ...other objects...
]
它可以有任何形状和数量的节点

我编写了一个方法,该方法应该递归地查找并返回根r和给定对象o之间的路径(一个中间对象数组)。(无论是否包括ro我都不在乎)

公共getPath(树:数组,o:object):数组{ let路径:数组=[]; 函数f(子树:数组):void{ for(子树的let节点){ push(节点['data']); if(node['data']==o)返回; else如果(节点['subs'].length>0)f(节点['subs']); else路径=[]; } } f(树); 返回路径; } 基本上我的想法是

  • 始终将从ro的遍历过程中访问的每个对象添加到数组中
  • 如果遍历的路径不是从ro的路径,则清空数组
  • 如果到达遍历应该结束的位置,则返回o
结果:

  • 它适用于r作为o,返回[r]
  • 它也适用于r的第一个子级,如o,返回[r,即r的第一个子级
  • 但是,如果选择任何其他对象作为o,则不仅返回正确路径的对象,还返回树的许多其他对象

代码的缺陷在于您使用的是全局(无论如何都超出了
f
的范围)
path
数组。问题是,如果某个节点不匹配,您将清除整个数组,而您应该只删除当前部分。有两种方法可以实现您想要的结果:第一种是使
f
接受一个数组
路径
,它会复制并递归传递该数组,直到找到对象为止;另一种最好的方法是使用调用堆栈(由递归创建):

公共getPath(树:数组,o:object):数组{ 函数f(subtree:Array){//我不知道typescript,所以将返回类型指定为(Array或null) for(子树的let节点){ 如果(node.data==o){//如果这是我们正在寻找的节点 return[node];//返回一个数组(这将是我们的路径),在这里可以返回[]以排除匹配的节点(o),也可以返回[node]以包含它 }否则,如果(node.subs.length){//不是我们要查找的节点,但它有子节点,那么让我们检查它们 让result=f(node.subs);//结果要么是一个数组(如果我们递归地找到某个东西),要么是null 如果(result){//如果我们发现了什么,那么结果将是从当前节点到对象o(不包括当前节点)的路径 result.unshift(node);//我们通过将当前节点推入结果数组(将其推到第一个位置)来包含当前节点 return result;//返回表示成功的结果(数组) } } } return null;//此子树中找不到对象,返回null表示未成功。有点多余,因为默认情况下会返回undefined,所以可以随意删除它 } 返回f(树); }
实际上,您正在将所有测试项推送到
路径
,而不管它们是否是搜索对象,即使它们位于指向该对象的正确路径上。。您应该从
f
返回一个值,并测试结果,以了解是否在此子树中找到该值,以及是否添加了路径。注意:将对象与
节点['data']==o
进行比较仅当它们是具有相同引用的相同对象时才有效,使用此函数并为其提供一个新创建的对象
getPath({a:val})
即使键和值相同也不起作用。它有效,并且您的注释非常有用,谢谢。关于递归的紧凑教程:)我希望它也能帮助其他人。
public getPath(tree: Array<object>, o: object): Array<object> {

  let path: Array<object> = [];

  function f(subtree: Array<object>): void {
    for (let node of subtree) {

      path.push(node['data']);
      if (node['data'] == o) return;
      else if (node['subs'].length > 0) f(node['subs']);
      else path = [];

    }
  }

  f(tree);
  return path;

}
public getPath(tree: Array<object>, o: object): Array<object> {

    function f(subtree: Array<object>) {                              // I don't know typescript, so specify the return type as (Array<object> or null)
        for (let node of subtree) {
            if (node.data == o) {                                     // if this is the node we're looking for
                return [node];                                        // return an array (which will be our path), here you can either return [] to exclude the matched node (o) or [node] to include it
            } else if(node.subs.length) {                             // not the node we are looking for, but it has children, so let check'em out 
                let result = f(node.subs);                            // result will either be an array (if we recursively found something), or null otherwise
                if(result) {                                          // if we found something, then result will be the path from the current node to the object o (the current node not included)
                    result.unshift(node);                             // we include the current node by pushing it into the result array (pushing it to the first position)
                    return result;                                    // return result (an array) to signal successfulness
                }
            }
        }
        return null;                                                  // the object o not found in this subtree, return null to signal unsuccessfullness. Kind of redundant, because undefined is returned by default, so feel free to remove it
    }

    return f(tree);    
}