List 在满足谓词(Scala)的每个元素上拆分一个列表

List 在满足谓词(Scala)的每个元素上拆分一个列表,list,scala,collections,List,Scala,Collections,在文本文件中,我有以下格式的数据: 1) text text 2) more text 3) even more text more even text even more text ... 我使用以下命令将其作为字符串列表阅读: val input = io.Source.fromFile("filename.txt").getLines().toList 我想将列表分解为子列表,以1)、2)等开头 我想到了: val subLists = input.foldRight( List(

在文本文件中,我有以下格式的数据:

1)
text
text
2)
more text
3)
even more text
more even text
even more text
...
我使用以下命令将其作为字符串列表阅读:

val input = io.Source.fromFile("filename.txt").getLines().toList
我想将列表分解为子列表,以
1)
2)
等开头

我想到了:

val subLists =
  input.foldRight( List(List[String]()) ) {
    (x, acc) =>
      if (x.matches("""[0-9]+\)""")) List() :: (x :: acc.head) :: acc.tail
      else (x :: acc.head) :: acc.tail
  }.tail

能否更简单地做到这一点?如果有一个内置的方法在每个满足谓词(hint,hint,library designers:)的元素上拆分集合,那将是一件非常好的事情。

foldRight
带有一个复杂的参数,这通常表明您可以使用递归编写它,并将其分解为自己的方法,当你这么做的时候。这是我想到的。首先,让我们概括一下 对于泛型方法,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)  
 }
现在,只需调用

 groupPrefix(input)(_ matches """\d+\)""")

我很荣幸,在伟大的@MartinOdersky旁边添加一个答案

从Scala 2.13中,我们可以使用
列表。展开

列表展开(输入){
案例无=>
没有一个
案例x::as=>
as.span(!\匹配(“\d+\)”“”)匹配{
大小写(前缀,Nil)=>
一些(x::前缀,List.empty)
大小写(前缀、后缀)=>
一些(x::前缀,后缀)
}
}

代码在处运行。

看看这个问题和公认的答案:可以像答案中那样使用迭代器,但这种情况更复杂,因为每个标题都不同,所以需要为标题添加第二个迭代器/列表,它不再优雅。递归看起来更干净。一个问题是:对于包含476k个元素和10000个分隔符的大量组(堆栈溢出)列表,这不起作用。堆栈是尾部递归方法吗?它不是尾部递归的,因为函数调用在返回其值之前依赖于
操作(因此在每次迭代时使用更多的堆栈空间)。但是,通过向函数中添加一个附加参数(通常称为累加器)使其具有尾部递归性相对简单。