Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/418.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_Arrays_Loops_Object_Recursion - Fatal编程技术网

Javascript 嵌套递归对象循环

Javascript 嵌套递归对象循环,javascript,arrays,loops,object,recursion,Javascript,Arrays,Loops,Object,Recursion,我有对象数组,它们也可以有自己的数组。我的主要目标是在整个树中找到一个具有给定id的对象,并通过显示该对象所在位置的对象名来获取该元素的readmap 例如,我有这样的数据对象: { id: '0', name: "Boys" children: [ { name: "Soldiers", children: [ { name: "Bravo" children:

我有对象数组,它们也可以有自己的数组。我的主要目标是在整个树中找到一个具有给定id的对象,并通过显示该对象所在位置的对象名来获取该元素的readmap

例如,我有这样的数据对象:

{
  id: '0',
  name: "Boys"
  children: [
   {
    name: "Soldiers",
    children: [
     {
       name: "Bravo"
       children: [
         {name: "Tom"},
         {name: "Andrew"}
       ]
     }
    ]
   },
   {
    name: "Runners",
    children: [
     {
       name: "Team B"
       children: [
         {name: "Mark"},
         {name: "David"}
       ]
     }
    ]
   }
  ]
}

我当前正在通过函数查找项

 function findByName (name, array) {
    for (const node of array) {
      if (node.name === name) return node;
      if (node.children) {
        const child = findByName(name, node.children);
        if (child) return child;
      }
    }
  }

但要实现我的目标,我还需要实现这一价值的路线图。比如说


当我想找到
“Tom”
时。除了
findByName
的结果外,我还想得到
{name:“Tom”,road:[“Boys”,“soldies”,“Bravo”]

您需要传递另一个处理路径的属性。首先将路径定义为空数组。由于您只关心名称,因此每次找到具有子节点的节点时,都可以将该名称推入该数组

然后继续将更新后的数组传递给递归函数。请参见下面的工作示例:

(我更新了函数以返回一个包含结果和路径的对象)

演示:

您需要传递另一个处理路径的属性。首先将路径定义为空数组。由于您只关心名称,因此每次找到具有子节点的节点时,都可以将该名称推入该数组

然后继续将更新后的数组传递给递归函数。请参见下面的工作示例:

(我更新了函数以返回一个包含结果和路径的对象)

演示:

您可以为调用函数中的每个级别添加路径,而无需移交路径

const
findByName=(数组,名称)=>{
for(数组的常量节点){
如果(node.name==name)返回{…节点,路径:[]};
if(节点子节点){
const child=findByName(node.children,name);
if(child)返回{…child,path:[node.name,…child.path]};
}
}
},
数据=[{id:'0',姓名:“男孩”,儿童:[{name:'soldies],儿童:[{name:'Bravo],儿童:[{name:'Tom},{name:'Andrew}]},{name:'Runners],儿童:[{name:'Team B],儿童:[{name:'Mark},{name:'David}]}]}];
log(findByName(数据'Tom'));

.as console wrapper{max height:100%!important;top:0;}
您可以为调用函数中的每个级别添加路径,而无需移交路径

const
findByName=(数组,名称)=>{
for(数组的常量节点){
如果(node.name==name)返回{…节点,路径:[]};
if(节点子节点){
const child=findByName(node.children,name);
if(child)返回{…child,path:[node.name,…child.path]};
}
}
},
数据=[{id:'0',姓名:“男孩”,儿童:[{name:'soldies],儿童:[{name:'Bravo],儿童:[{name:'Tom},{name:'Andrew}]},{name:'Runners],儿童:[{name:'Team B],儿童:[{name:'Mark},{name:'David}]}]}];
log(findByName(数据'Tom'));

.as控制台包装{最大高度:100%!重要;顶部:0;}
我喜欢这种类型或问题的生成器,因为它允许您选择一个、多个或所有结果。此外,生成器向调用者提供控制,允许您在对结果满意时停止搜索。这可以通过单个函数实现-

function*select(a=[],query=Boolean,path=[])
{for(常数a)
{if(query(t))产生{…t,path}
yield*select(t.children,query,[…path,t.name])
}
}
常量数据=
[{id:'0',name:'Boys],children:[{name:'soldies],children:[{name:'Bravo],children:[{name:'Tom},{name:'Andrew}]},{name:'Runners],children:[{name:'B队],children:[{name:'Mark},{name:'David}]}]}]
//选择“汤姆”或“马克”
for(select的常数(数据,v=>v.name='Tom'| | v.name=='Mark'))
console.log(“找到:”,r)

我喜欢这种类型或问题的生成器,因为它允许您选择一个、多个或所有结果。此外,生成器向调用者提供控制,允许您在对结果满意时停止搜索。这可以通过单个函数实现-

function*select(a=[],query=Boolean,path=[])
{for(常数a)
{if(query(t))产生{…t,path}
yield*select(t.children,query,[…path,t.name])
}
}
常量数据=
[{id:'0',name:'Boys],children:[{name:'soldies],children:[{name:'Bravo],children:[{name:'Tom},{name:'Andrew}]},{name:'Runners],children:[{name:'B队],children:[{name:'Mark},{name:'David}]}]}]
//选择“汤姆”或“马克”
for(select的常数(数据,v=>v.name='Tom'| | v.name=='Mark'))
console.log(“找到:”,r)

重新打开。具有不同的结构,子体作为对象属性,而不是子体作为对象属性。重新打开。具有不同的结构,子体作为对象属性,而不是子体作为对象属性。我知道有很好的理由重新打开它!我写了几个不同的答案,没有一个是h似乎提供了任何很棒的东西,所以我没有发布它们。我完全不奇怪你给出了一个优雅的答案!一个诡辩:我的名字
find
Array.prototype.find
及其短路返回。类似
select
query
match
的东西击中了我我更清楚。我特别喜欢
select
。我很高兴能做出有价值的贡献^ ^我也喜欢
select
,现在更新答案。我知道有一个很好的理由重新打开这个!我写了几个不同的答案,没有一个看起来很好,所以我没有发布它们。我真的很高兴
function findByName(name, array, path = []) {
  for (const node of array) {
    if (node.name === name) return {result: node, path};
    if (node.children) {
      path.push(node.name) // We update the path with the current node name that has children
      const child = findByName(name, node.children, path );
      if (child) return { result: child, path};
    }
  }
}