Split up a list at each element satisfying a predicate (Scala)

后端 未结 2 1729
谎友^
谎友^ 2020-12-10 13:36

In a text file I have data in the form:

1)
text
text
2)
more text
3)
even more text
more even text
even more text
...

I read it as a list o

相关标签:
2条回答
  • 2020-12-10 14:01

    foldRight with a complicated argument is usually an indication that you might as well write this using recursion, and factor it out to its own method, while you are at it. Here's what I came up with. First, let's generalize to a generic method, groupPrefix:

     /** Returns shortest possible list of lists xss such that
      *   - xss.flatten == xs
      *   - No sublist in xss contains an element matching p in its tail
      */
     def groupPrefix[T](xs: List[T])(p: T => Boolean): List[List[T]] = xs match {
       case List() => List()
       case x :: xs1 => 
         val (ys, zs) = xs1 span (!p(_))
         (x :: ys) :: groupPrefix(zs)(p)  
     }
    

    Now you get the result simply by calling

     groupPrefix(input)(_ matches """\d+\)""")
    
    0 讨论(0)
  • 2020-12-10 14:04

    I have the honor, to add an answer next to the great @MartinOdersky!

    From Scala 2.13 we can use the List.unfold:

    List.unfold(input) {
      case Nil =>
        None
      case x :: as =>
        as.span(!_.matches("""\d+\)""")) match {
          case (prefix, Nil) =>
            Some(x :: prefix, List.empty)
          case (prefix, suffix) =>
            Some(x :: prefix, suffix)
        }
    }
    

    Code run at Scastie.

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