scala - muliline string split

你。 提交于 2019-12-17 22:03:34

问题


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

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!