Algorithm 获取任何节点的顶级父节点

Algorithm 获取任何节点的顶级父节点,algorithm,scala,data-structures,tree,Algorithm,Scala,Data Structures,Tree,根据问题末尾的格式,获取给定项的顶级名称的最佳方法是什么? 顶级名称是parentId=1的名称 def gettoplavel(名称:String):String={ //Environment(150)->Environment(150)-因为它的parentId是1 //暗杀->安全-自暗杀(12)->恐怖主义(10)->安全(2) } 这是我目前的方法,但有更好的方法吗 未映射=categories.size 循环浏览此列表,直到仍有未映射的项。 -为顶层构建映射(Int、String

根据问题末尾的格式,获取给定项的顶级名称的最佳方法是什么? 顶级名称是parentId=1的名称

def gettoplavel(名称:String):String={
//Environment(150)->Environment(150)-因为它的parentId是1
//暗杀->安全-自暗杀(12)->恐怖主义(10)->安全(2)
}
这是我目前的方法,但有更好的方法吗

未映射=categories.size

循环浏览此列表,直到仍有未映射的项。
-为顶层构建映射(Int、String)。
-构建映射(Int,Int)-将id映射到顶级id。
-跟踪未映射的项目

一旦循环退出,我就可以使用这两个映射来完成工作

[
    {
        "name": "Destination Overview",
        "id": 1,
        "parentId": null
    },
    {
        "name": "Environment",
        "id": 150,
        "parentId": 1
    },
    {
        "name": "Security",
        "id": 2,
        "parentId": 1
    },
    {
        "name": "Armed Conflict",
        "id": 10223,
        "parentId": 2
    },
    {
        "name": "Civil Unrest",
        "id": 21,
        "parentId": 2
    },
    {
        "name": "Terrorism",
        "id": 10,
        "parentId": 2
    },
    {
        "name": "Assassination",
        "id": 12,
        "parentId": 10
    }
]

这实际上是两个问题

  • 将Json解析为Scala集合并
  • 使用该集合将项目追溯到顶级父级
  • 对于第一个问题,您可以使用。第二部分可以用尾部递归函数处理。以下是解决这两个问题的完整程序:

    import play.api.libs.json.{Json, Reads}
    
    case class Node(name: String, id: Int, parentId: Option[Int])
    object JsonParentFinder {
      def main(args: Array[String]): Unit = {
        val s =
          """
            |[
            |    {
            |        "name": "Destination Overview",
            |        "id": 1,
            |        "parentId": null
            |    },
            |    {
            |        "name": "Environment",
            |        "id": 150,
            |        "parentId": 1
            |    },
            // rest of the json
            |]
            |""".stripMargin
    
        implicit val NodeReads : Reads[Node] =Json.reads[Node]
        val r = Json.parse(s).as[Seq[Node]]
          .map(x => x.id -> x).toMap
    
        println(getTopLevelNode(150, r))
        println(getTopLevelNode(12, r))
      }
    
      def getTopLevelNode(itemId : Int, nodes: Map[Int, Node], path : List[Node] = List.empty[Node]) : List[Node] = {
        if(nodes(itemId).id == 1)
          nodes(itemId) +: path  
        else
          getTopLevelNode(nodes(nodes(itemId).parentId.get).id, nodes, nodes(itemId) +: path)
      }
    }
    
    输出将是:

    List(Node(Destination Overview,1,None), Node(Environment,150,Some(1)))
    List(Node(Destination Overview,1,None), Node(Security,2,Some(1)), Node(Terrorism,10,Some(2)), Node(Assassination,12,Some(10)))
    
    请注意:

    • 我还没有实现全面的错误处理逻辑。隐式假设是parentId==None的唯一项是根节点<代码>节点(itemId).parentId.get可能导致失败
    • 另外,在创建地图时,假设所有项目都有唯一的ID
    • 另一个假设是,所有节点最终都有一条到根节点的路径。如果不是这样,这将失败。但是,通过添加更多的停止条件来修复这些情况应该很简单
    • 我将项目预先添加到累加器列表中(此处名为
      path
      ),因为对Scala列表的预先添加操作需要固定的时间。您可以
      反转
      结果列表,或者使用另一种数据结构,如
      Vector
      来高效地构建路径