在Scala中变异一般树的节点

时间:2018-10-11 08:55:42

标签: scala functional-programming

请考虑以下标准类:

class Node(val data: NodeData, val children: Seq[Node])

NodeData类也很简单:

case class NodeData(text: String, foo: List[Bar])

此外,树具有任意深度,它不是固定的。

很显然,对于惯用的Scala,在该结构上执行呼吸优先或深度优先搜索是微不足道的。但是,请考虑我不仅要访问这些节点中的每个节点,而且还希望在每次访问时对它们进行突变。更具体地说,我想对那个foo列表中的对象进行突变。我将如何实施呢?我想到的一种方法是在遍历节点时以某种方式更新节点并构建新树,但是我的直觉告诉我,有一个比这更简单的解决方案。

1 个答案:

答案 0 :(得分:1)

如果您真的想保持不变,则可以在recMap上定义一个函数Node,如下所示:

def recMap(f: NodeData => NodeData) : Node = Node(f(data), children.map(_.recMap(f)))

然后您可以像本示例中一样使用它(我也将Node设置为案例类):

type Bar = Int

case class NodeData(text: String, foo: List[Bar])

case class Node(data: NodeData, children: Seq[Node]) {

  def recMap(f: NodeData => NodeData) : Node = Node(f(data), children.map(_.recMap(f)))
}

val tree = new Node(NodeData("parent", List(1, 2, 3, 4)), Seq(
  Node(NodeData("a child", List(5, 6, 7, 8)), Seq.empty),
  Node(NodeData("another child", List(9, 10, 11, 12)), Seq.empty)
))

val modifiedTree = tree.recMap(
  data => NodeData(
    if(data.text == "parent") "I am the parent!" else "I am a child!",
    data.foo.filter(_ % 2 == 0)
  )
)

println(modifiedTree)

Try it out!

也许这就是您要搜索的内容。