2010-10-28 13 views
6

J'essaie d'intégrer une application Lift dans un code Java existant. Dans l'un de mes extraits, j'ai un tableau d'objets Java dont j'ai besoin pour mapper dans un NodeSeq. Je peux obtenir un tableau de nœuds, mais pas un NodeSeq. (Au moins, pas de manière très fonctionnelle).Comment convertir Array [Node] en 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 

Quelle est la façon la plus propre de faire cela?

+1

Vous avez toujours la méthode '++' à votre disposition :-) 'new NodeSeq() ++ theArray_Elm_thing'. Il peut y avoir de meilleurs moyens. Codage heureux. –

+1

NodeSeq est abstrait, donc 'new NodeSeq()' ne fonctionne pas. –

Répondre

8

Je voudrais simplement convertir la sortie map à la séquence (étant donné que Seq[Node] est un super-classe de NodeSeq)

scala> def foo: NodeSeq = data.map { s => <x>{s}</x> } toSeq 
foo: scala.xml.NodeSeq 

ou utiliser foldLeft au lieu de map

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

toSeq est l'élégance que je cherche. Merci! – leedm777

+0

Utiliser map puis toSeq signifie que vous créez 2 collections. En utilisant breakOut vous créez 1. – IttayD

+2

'toSeq' crée un wrapper (http://www.scala-lang.org/api/current/scala/collection/mutable/WrappedArray.html), donc il y a une pénalité de performance misérable. http://www.scala-lang.org/docu/files/collections-api/collections_38.html –

9
scala> import collection.breakOut 
import collection.breakOut 

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

La carte de méthode a en réalité deux listes d'arguments. Le premier accepte une fonction, que vous avez passée. La seconde accepte un objet CanBuildFrom qui est utilisé pour créer un générateur qui construit ensuite la séquence retournée. Cet argument est implicite, donc habituellement le compilateur le remplit pour vous. Il accepte 3 types de paramètres: From, T, To. Il existe plusieurs implicits predef (y compris dans l'objet NodeSeq), mais aucun ne correspond à From = Array, T = Node, To = NodeSeq. Breakout résout ceci: c'est une méthode générique qui retourne une instance CanBuildFrom en recherchant un CanBuildFrom implicite [Nothing, T, To]. Selon les règles de recherche implicite, tout CanBuildFrom qui correspond à T, To et a From> Nothing est acceptable. Dans ce cas: canBuildFrom dans l'objet Tableau

+2

Il semblait approprié de lier à la question breakOut: http://stackoverflow.com/questions/1715681/scala-2-8-breakout –

1

Vous recherchez cette méthode sur l'objet compagnon NodeSeq.

NodeSeq.fromSeq(s: Seq[Node])