2011-12-19 13 views
8

Ho una lista di stringhe e ho bisogno di unirle insieme ai tag < br /> in mezzo. Così a partire da:Unire stringhe con nodo XML tra in scala

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

ho bisogno di finire con un NodeSeq di:

line1<br/>line2<br/>line3 

E 'possibile la lista contiene un solo elemento, nel qual caso avrei dovuto finire con un NodeSeq solo di testo ("Linea 1").

Esiste un solo liner per eseguire questa operazione, utilizzando una delle funzioni di ordine superiore nell'elenco? Ho provato a giocare con foldLeft ma non riesco a convincerlo a fare ciò che voglio.

risposta

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

Nota che dobbiamo allargare il tipo di scala.xml.NodeSeq manualmente Text è troppo restrittivo per il metodo reduce. Il più conciso

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

non verrà compilato.

+0

Forse mi manca qualcosa, ma ottengo un errore di compilazione su "reduce" dicendo che il metodo non è stato trovato nell'elenco. Devo usare ridurre Left o ridurre Right, correggere? – user1106210

+0

Hmm, funziona per me. Stai usando 2.9.1? – Debilski

+0

Ah ecco perché. Ho avviato la console in un progetto casuale sulla mia macchina, che risulta essere 2.8.1. – user1106210

3

Se non ti dispiace utilizzando Scalaz, c'è intersperse:

import scalaz._ 
import Scalaz._ 

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

d'accordo con quello Debilski ha risposto. Solo un altro modo per raggiungere lo stesso è,

import scala.xml._

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

Ma usando la mappa/ridurre è un approccio molto più pulito.

+0

Questo praticamente si interrompe su input non validi come 'List (" <")'. – Debilski

+1

Non l'ho menzionato nel problema, ma questo è un input non pubblicizzato. Il tuo approccio funziona, ma se l'elenco contiene stringhe come "asdf", vengono analizzate anziché visualizzate, lasciando aperta una webapp per attaccare. – user1106210