嵌套递归对象循环 [英] Nested recursive object loop

查看:45
本文介绍了嵌套递归对象循环的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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

<预><代码>{编号:'0',名称:《男孩》孩子们: [{名称:士兵",孩子们: [{名称:Bravo"孩子们: [{名称:汤姆"},{名称:安德鲁"}]}]},{名称:跑步者",孩子们: [{名称:《B队》孩子们: [{名称:标记"},{名称:大卫"}]}]}]}

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

 function findByName (name, array) {for(数组的常量节点){if (node.name === name) 返回节点;如果(节点.孩子){const child = findByName(name, node.children);如果(孩子)返回孩子;}}}

但是为了实现我的目标,我还需要实现该价值的路线图.例如.

当我想找到 Tom" 时.除了 findByName 的结果,我想得到 {name: "Tom", road: ["Boys", "Soldiers", "Bravo"]

解决方案

我喜欢这种类型或问题的生成器,因为它允许您选择一个、多个或所有结果.此外,生成器将控制权交给调用者,允许您在对结果满意时停止搜索.这可以通过一个函数来完成 -

function* select(a = [], query = Boolean, path = []){ for (const t of a){ if (query(t)) yield { ...t, path }yield *select(t.children, query, [...path, t.name])}}常量数据 =[{ 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" }] }] }] }]//选择汤姆"或马克"for (const r of select(data, v => v.name == 'Tom' || v.name == "Mark"))console.log("找到:", r)

发现:{姓名":汤姆",路径":[男孩",《士兵》,布拉沃"]}成立: {名称":标记",路径":[男孩",《跑者》,《B队》]}

如果你只想要 first 结果,我们可以使用 returnbreak,搜索立即停止,可能会节省许多浪费的计算 -

函数优先(它){ for (const x of it)return x//<- 返回并停止搜索}首先(选择(数据,v => v.name ==安德鲁"))

{姓名":安德鲁",路径":[男孩",《士兵》,布拉沃"]}

如果你想要所有的结果,我们可以使用Array.from.因为select 很灵活,它允许我们做各种有用的查询-

Array.from(select(data, v => !v.children), r => r.name)

[汤姆",安德鲁",马克",大卫"]

I have arrays of objects that can also have arrays of their own. My main goal is to find an object with a given id in the whole tree and get readmap to that element by displaying the names of the objects names where it occurs.

For example I have data object like this:

{
  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"}
       ]
     }
    ]
   }
  ]
}

I am currently finding an item by a function

 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;
      }
    }
  }

But to achive my goal I need also roadmap to that value. For example.

When I want to find "Tom". Besides results of findByName I would like to get {name: "Tom", road: ["Boys", "Soldiers", "Bravo"]

解决方案

I like generators for this kind or problem because it allows you to select one, many, or all results. Additionally generators give control to the caller, allowing you to stop searching whenever you are satisfied with the result. This can be accomplished with a single function -

function* select(a = [], query = Boolean, path = [])
{ for (const t of a)
  { if (query(t)) yield { ...t, path }
    yield *select(t.children, query, [...path, t.name])
  }
}

const data =
  [{ 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" }] }] }] }]

// select "Tom" OR "Mark"
for (const r of select(data, v => v.name == 'Tom' || v.name == "Mark"))
  console.log("found:", r)
  

found: {
  "name": "Tom",
  "path": [
    "Boys",
    "Soldiers",
    "Bravo"
  ]
}
found: {
  "name": "Mark",
  "path": [
    "Boys",
    "Runners",
    "Team B"
  ]
}

If you want only the first result, we can use return or break, and searching stops immediately, potentially saving many wasted computations -

function first (it)
{ for (const x of it)
    return x              // <- return and stop searching
}

first(select(data, v => v.name == "Andrew"))

{
  "name": "Andrew",
  "path": [
    "Boys",
    "Soldiers",
    "Bravo"
  ]
}

If you want all of the results, we can use Array.from. Because select is flexible, it allows us to do all sorts of useful queries -

Array.from(select(data, v => !v.children), r => r.name)

[
  "Tom",
  "Andrew",
  "Mark",
  "David"
]

这篇关于嵌套递归对象循环的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆