2011-12-19 8 views
8

Tengo una lista de cadenas y necesito unirlas junto con < br /> etiquetas entre ellas. Así que a partir de:Unir cadenas con nodo XML entre en scala

val list = List("line1", "line2", "line3") 

que necesito para terminar con un NodeSeq de:

line1<br/>line2<br/>line3 

Es posible que la lista contiene sólo un elemento, en cuyo caso debería terminar con un NodeSeq acaba de texto ("línea 1").

¿Hay un trazador de líneas para hacer esto, usando una de las funciones de orden superior en la lista? Intenté jugar con foldLeft pero parece que no puedo hacer lo que quiero.

Respuesta

12
list.map(scala.xml.Text(_):scala.xml.NodeSeq).reduce(_ ++ <br /> ++ _) 

Tenga en cuenta que tenemos que ampliar el tipo de scala.xml.NodeSeq manualmente como Text es demasiado restrictivo para el método reduce. El más conciso

list.map(scala.xml.Text).reduce(_ ++ <br /> ++ _) 

no se compilará.

+0

Tal vez me falta algo, pero obtengo un error de compilación en "reducir" diciendo que el método no se encontró en la lista. Necesito usar reduceLeft o reduceRight, ¿correcto? – user1106210

+0

Hmm, funciona para mí. ¿Estás usando 2.9.1? – Debilski

+0

Ah, es por eso. Inicié la consola en un proyecto aleatorio en mi máquina, que resultó ser 2.8.1. – user1106210

3

Si no les importa usar Scalaz, hay intersperse:

import scalaz._ 
import Scalaz._ 

list.map(xml.Text(_): xml.Node).intersperse(<br/>): xml.NodeSeq 
0

de acuerdo con lo Debilski ha contestado. Sólo otra manera de conseguir el mismo es,

import scala.xml._

XML.loadString("<root>" + list.mkString("<br/>") + "</root>").child:NodeSeq

Pero el uso de map/reduce es un enfoque mucho más limpio.

+0

Eso se rompe en entradas inválidas como 'List (" <")'. – Debilski

+1

No lo mencioné en el problema, pero esta es una entrada no optimizada. Su enfoque funciona, pero si la lista contiene cadenas como "asdf", se analizan en lugar de mostrarse, dejando una aplicación web abierta para atacar. – user1106210

Cuestiones relacionadas