问题
I have this:
val msg = "Preparado para cocinar..."
val message = msg.splitAt(msg.length()/2)
println(message._1 + "\n" + message._2.trim())
The problem is that I am getting this result (bcz I am just spliting it at the middle):
Preparado pa
ra cocinar...
How I can have a multi(not only in 2 parts) displayed message but it should be separated in spaces
not in the middle of the sentence?
回答1:
A reasonably elegant functional solution
def wordWrap(s: String, n: Int) = s.split("\\s").foldLeft(List[String]())
{ (lines, word) =>
if (lines.isEmpty || lines.head.length + word.length + 1 > n)
word :: lines
else
(lines.head + " " + word) :: lines.tail
}
.reverse
wordWrap( "Preparado para cocinar...", 23)
// List(Preparado para, cocinar...)
wordWrap( "Preparado para cocinar...", 5)
// List(Preparado, para, cocinar...)
wordWrap("A quick brown fox jumps over the lazy dog.", 10)
// List(A quick, brown fox, jumps over, the lazy, dog. )
A variant that just checks the empty list once
def wordWrap(s: String, n: Int) = {
val words = s.split("\\s")
if (words.isEmpty) Nil
else
words.tail.foldLeft(List[String](words.head)){ (lines, word) =>
if (lines.head.length + word.length + 1 > n)
word :: lines
else
(lines.head + " " + word) :: lines.tail
}.reverse
}
回答2:
A not very elegant working solution,
val a = msg.split("\\s") // Split by space
a = Array(Preparado, para, cocinar...)
val n = a.size / 2 // Get halving point rounded to lower closest integer
n = 1
val b = Array(a.take(n).mkString, a.drop(n).mkString(" ")) // Halve the array
b = Array(Preparado, para cocinar...)
b.foreach(println) // Print it
Preparado
para cocinar...
Update
As pointed out by @AdrienAubel, consider the use of splitAt
over the split array,
val (b1,b2) = a.splitAt(n)
b1 = Array(Preparado)
b2 = Array(para, cocinar...)
println(b1.mkString(" "))
Preparado
println(b2.mkString(" "))
para cocinar...
回答3:
Another quite inelegant functional solution.
I'm pretty sure something better will come given some thought
Code
def divide(msg: String): (String, String) = {
//index each letter
val indexed = msg.zipWithIndex
//split at first blank space after midpoint
val (fst, snd) = indexed span {case (c, i) => i < indexed.size/2 || c != ' '}
//utility to recompose indexed parts
def unzipString(s: Seq[(Char, Int)]) = s.map(_._1).mkString.trim
//get separated lines
(unzipString(fst), unzipString(snd))
}
REPL
scala> val msg = "Parando para cocinar..."
msg: String = Parando para cocinar...
scala> val indexed = msg.zipWithIndex
indexed: scala.collection.immutable.IndexedSeq[(Char, Int)] = Vector((P,0), (a,1), (r,2), (a,3), (n,4), (d,5), (o,6), ( ,7), (p,8), (a,9), (r,10), (a,11), ( ,
12), (c,13), (o,14), (c,15), (i,16), (n,17), (a,18), (r,19), (.,20), (.,21), (.,22))
scala> val (fst, snd) = indexed span {case (c, i) => i < indexed.size/2 || c != ' '}
fst: scala.collection.immutable.IndexedSeq[(Char, Int)] = Vector((P,0), (a,1), (r,2), (a,3), (n,4), (d,5), (o,6), ( ,7), (p,8), (a,9), (r,10), (a,11))
snd: scala.collection.immutable.IndexedSeq[(Char, Int)] = Vector(( ,12), (c,13), (o,14), (c,15), (i,16), (n,17), (a,18), (r,19), (.,20), (.,21), (.,22))
scala> def unzipString(s: Seq[(Char, Int)]): String = s.map(_._1).mkString.trim
unzipString: (s: Seq[(Char, Int)])String
scala> (unzipString(fst), unzipString(snd))
res2: (String, String) = (Parando para,cocinar...)
Updated: the original answer had a couple of blatantly obvious errors
来源:https://stackoverflow.com/questions/27122150/scala-muliline-string-split