这是我之前发表的
one篇文章的后续内容.
我试着理解为什么RuleTransformer表现如此糟糕.现在我认为它很慢,因为它的复杂性是O(2n),其中n是输入XML树的高度.
import scala.xml._,scala.xml.transform._ val rule: RewriteRule = new RewriteRule() { override def transform(node: Node): Seq[Node] = node match { case e: Elem => e.copy(label = "b") case other => other } } def trans(node: Node): Node = new RuleTransformer(rule).apply(node)
让我们计算转换访问输入< a3>< a2>< a1 />< / a2>< / a3>中每个节点的次数.
为了计算访问次数,我们添加了一个访问的缓冲区,在开始时初始化它,存储访问过的节点,最后打印它.
import scala.collection.mutable.ListBuffer // buffer to store visited nodes var visited: ListBuffer[Node] = ListBuffer[Node]() val rule: RewriteRule = new RewriteRule() { override def transform(n: Node): Seq[Node] = { visited append (n) // count this visit n match { case e: Elem => e.copy(label = "b") case other => other } } } def trans(node: Node): Node = { visited = ListBuffer[Node]() // init the buffer val r = new RuleTransformer(rule).apply(node) // print visited nodes and numbers of visits println(visited.groupBy(identity).mapValues(_.size).toSeq.sortBy(_._2)) r }
现在让我们在REPL中运行它并查看访问过的内容
scala> val a3 = <a3><a2><a1/></a2></a3> a3: scala.xml.Elem = <a3><a2><a1/></a2></a3> scala> trans(a3) ArrayBuffer((<a3><b><b/></b></a3>,2),(<a2><b/></a2>,4),(<a1/>,8)) res1: scala.xml.Node = <b><b><b/></b></b>
所以a1被访问了八次.
如果我们转换< a4>< a3>< a2>< a1 />< / a2>< / a3>< / a4>那么a1将被访问16次,对于< a5>< a4>< a3>< a2>< a1 />< / a2>< / a3>< / a4>< / a5> ; – 32等等因此复杂性看起来呈指数级.
是否有意义 ?你如何通过分析code来证明这一点?
解决方法
这不是一个非常严格的分析,但问题似乎是BasicTransformer的变换(Seq [Node])方法[1].
子变换方法将针对更改的节点调用两次.特别是在您的示例中,由于这个原因,将调用所有节点两次.你是对的,高度为h的每个节点将被称为2 ^(h-1)次.另请注意,节点的最多一个子节点将被调用两次,因为使用了span和代码,在特定示例中,节点的所有子节点将被调用两次.
只是为了验证这是为修改后的RulesTransformer编写了这些代码示例. (我也可以覆盖RulesTransformer.但无论如何)
// This is same as library RuleTransformer added with print statement class copiedRuleTransformer(rules: RewriteRule*) extends BasicTransformer { override def transform(n: Node): Seq[Node] = { println(n) rules.foldLeft(super.transform(n)) { (res,rule) => rule transform res } } }
我修改过的RuleTransformer
class MyRuleTransformer(rules: RewriteRule*) extends BasicTransformer { override def transform(n: Node): Seq[Node] = { println(n) rules.foldLeft(super.transform(n)) { (res,rule) => rule transform res } } override def transform(ns:Seq[Node]): Seq[Node] = { ns.flatMap(n => transform(n)) } }
这些代码仅用于演示目的.
你可以称之为
new copiedRuleTransformer(rule).apply(node)
要么
new MyRuleTransformer(rule).apply(node)
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。