scala - muliline string split

后端 未结 3 829
太阳男子
太阳男子 2020-12-12 03:10

I have this:

val msg = \"Preparado para cocinar...\"
val message = msg.splitAt(msg.length()/2)

println(message._1 + \"\\n\" + message._2.trim())


        
相关标签:
3条回答
  • 2020-12-12 03:14

    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...
    
    0 讨论(0)
  • 2020-12-12 03:19

    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
      }
    
    0 讨论(0)
  • 2020-12-12 03:35

    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

    0 讨论(0)
提交回复
热议问题