迭代更新scalaz树
我有一个路径列表:迭代更新scalaz树,scala,scalaz,zipper,Scala,Scalaz,Zipper,我有一个路径列表: val paths = List(List("foo"), List("bar", "a"), List("bar", "b")) 我想在scalaz树中表示: def pathsToTree(root: String, paths: List[List[String]]): Tree[String] = ??? 结果: pathsToTree("paths", paths) => "paths".node("foo".leaf, "bar".node("a".l
val paths = List(List("foo"), List("bar", "a"), List("bar", "b"))
我想在scalaz树中表示:
def pathsToTree(root: String, paths: List[List[String]]): Tree[String] = ???
结果:
pathsToTree("paths", paths)
=> "paths".node("foo".leaf, "bar".node("a".leaf, "b".leaf))
我从中读过一些关于TreeLoc
,但使用左/右索引或子索引似乎相当乏味。我想象这样做:
paths.foldLeft(root.node()) { case (acc: Tree[String], path: List[String]) =>
acc // how to add all the items from `path` to the tree?
}
看起来我可以使用
find
和setTree
或modifyTree
但这似乎效率很低。这是通用生成器:
def pathTree[E](root: E, paths: Seq[Seq[E]]): Tree[E] =
root.node(paths groupBy (_.head) map {
case (parent, subpaths) => pathTree(parent, subpaths collect {
case parent +: rest if rest.nonEmpty => rest
})
} toSeq: _*)
对于在线修改,我们可以定义:
def addPath[E](path: Seq[E], tree: Tree[E]): Tree[E] = if (path.isEmpty) tree
else
tree match {
case Tree.Node(root, children) if children.exists(_.rootLabel == path.head) => root.node(
children map (subtree => if (subtree.rootLabel == path.head) addPath(path.tail, subtree) else subtree): _*
)
case Tree.Node(root, children) => root.node(children :+ path.init.foldRight(path.last.leaf)((root, sub) => root.node(sub)): _*)
}
所以
屈服
"root"
|
+- "foo"
|
`- "bar"
|
+- "b"
| |
| `- "c"
|
`- "a"
和println(addPath(Seq(“foo”,“baz”),tree).drawTree)
prints
"root"
|
+- "foo"
| |
| `- "baz"
|
`- "bar"
|
+- "b"
| |
| `- "c"
|
`- "a"
回答得很好。非常感谢。请注意,如果存在children.exists(uu.rootLabel==path.head),则在位于
的addPath中缺少一个)
。我无法编辑,因为编辑必须更改超过6个字符:(
"root"
|
+- "foo"
| |
| `- "baz"
|
`- "bar"
|
+- "b"
| |
| `- "c"
|
`- "a"