如何将Array [Node]转换为NodeSeq?

lee*_*777 7 scala lift scala-2.8

我正在尝试将Lift应用程序集成到一些现有的Java代码中.在我的一个片段中,我有一个Java对象Array,我需要将它映射到NodeSeq.我可以获得一个节点数组,但不能获得NodeSeq.(至少,不是以非常实用的方式).

import scala.xml.NodeSeq

// pretend this is code I can't do anything about
val data = Array("one", "two", "three")

// this is the function I need to write
def foo: NodeSeq = data.map { s => <x>{s}</x> }
//                          ^
// error: type mismatch;
//  found   : Array[scala.xml.Elem]
//  required: scala.xml.NodeSeq
Run Code Online (Sandbox Code Playgroud)

最干净的方法是什么?

Itt*_*ayD 10

scala> import collection.breakOut
import collection.breakOut

scala> def foo: NodeSeq = data.map { s => <x>{s}</x> }(breakOut)
foo: scala.xml.NodeSeq
Run Code Online (Sandbox Code Playgroud)

方法映射实际上有两个参数列表.第一个接受您传递的函数.第二个接受CanBuildFrom对象,该对象用于创建构建器,然后构建返回序列.这个参数是隐含的,所以通常编译器会为你填充它.它接受3种类型参数:From,T,To.有几个pref implicits(包括在对象NodeSeq中),但它们都不匹配From = Array,T = Node,To = NodeSeq.

breakOut解决了这个问题:它是一个泛型方法,通过搜索隐式CanBuildFrom [Nothing,T,To]来返回CanBuildFrom实例.根据隐式搜索规则,任何匹配T,To且具有From> Nothing的CanBuildFrom都是可接受的.在这种情况下:对象Array中的canBuildFrom

  • 链接到breakOut问题似乎很合适:http://stackoverflow.com/questions/1715681/scala-2-8-breakout (2认同)

Vas*_*iuk 8

我只是将map输出转换为序列(假设Seq[Node]是超类NodeSeq)

scala> def foo: NodeSeq = data.map { s => <x>{s}</x> } toSeq
foo: scala.xml.NodeSeq
Run Code Online (Sandbox Code Playgroud)

或使用foldLeft而不是map

scala> def foo: NodeSeq = (Seq[Node]() /: data) {(seq, node)=> seq ++ <x>{node}</x>}
foo: scala.xml.NodeSeq
Run Code Online (Sandbox Code Playgroud)

  • `toSeq`创建了一个包装器(http://www.scala-lang.org/api/current/scala/collection/mutable/WrappedArray.html),因此会有一个悲惨的性能损失.http://www.scala-lang.org/docu/files/collections-api/collections_38.html (2认同)