【问题标题】:Transforming XML to a list of Elements in Scala将 XML 转换为 Scala 中的元素列表
【发布时间】:2014-10-20 15:14:46
【问题描述】:

这是我上一个问题的后续。我想急切地线性化 XML 树(不是懒惰)。为简单起见,我假设 XML 树是 Elem 节点的树,因此我将 XML 转换为 Elem 的序列。

import scala.xml.{Elem, Node}
import PartialFunction._

def linearize(node: Node): List[Node] = {
  val children = node.child.filter(cond(_) {case _: Elem => true}).toList
  children match {
    case Nil => List(node)
    case list => node :: list.flatMap(linearize)
  }
}

它似乎有效,但我不喜欢 val children = ... 你如何建议更改/修复它?

【问题讨论】:

    标签: xml scala collections


    【解决方案1】:

    由于您已经将node.child 转换为List,因此您无需对其进行匹配,您可以直接使用flatMap,因为如果child 为空,它将返回Nil。以下代码产生的结果与您的简单测试用例解决方案相同。

    import scala.xml.{Elem, Node}
    import PartialFunction._
    
    def linearize(node: Node): List[Node] = {
    
      node :: node.child.flatMap {
        case e: Elem => linearize(e)
        case _ => Nil
      }.toList
    
    }
    

    【讨论】:

    • 谢谢。如果node.child 包含非Elem 节点怎么办?
    • 好吧,这取决于你想用它们做什么。我刚刚将匹配添加到Elem,因此它的行为类似于问题上发布的函数。 PS。如果这完全回答了您的问题,您能否将其标记为答案而不是投票?如果答案不完整,我可以补充。
    【解决方案2】:

    您可以以depth-first and breath-first 两种方式遍历树。我已经为这两种模式创建了函数。两者都是尾递归的,因此您可以以牺牲堆为代价来节省一些堆栈帧。

    import scala.xml.{ Elem, Node }
    
    def linearizeDepthFirst(node: Node): List[Node] = {
      @annotation.tailrec
      def loop(toVisit: Vector[Node], result: Vector[Node]): List[Node] = {
        if (toVisit.isEmpty) {
          result.toList
        } else {
          val children = toVisit.head.collect({ case e: Elem => e }).toVector
          loop(children ++ toVisit.tail, result ++ children)
        }
      }
    
      loop(Vector(node), Vector(node))
    }
    
    def linearizeBreadthFirst(node: Node): List[Node] = {
      @annotation.tailrec
      def loop(toVisit: Vector[Node], result: Vector[Node]): List[Node] = {
        if (toVisit.isEmpty) {
          result.toList
        } else {
          val children = toVisit.head.collect({ case e: Elem => e }).toVector
          loop(toVisit.tail ++ children, result ++ children)
        }
      }
    
      loop(Vector(node), Vector(node))
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-01-21
      • 2015-02-13
      • 1970-01-01
      • 2018-07-20
      • 2018-08-03
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多