在文本文件中,我有以下格式的数据:
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
这可以更简单地实现吗?如果有一个内置方法可以在满足谓词的每个元素上拆分集合(提示,提示,库设计者:),那将会是非常好的。
答案 0 :(得分:24)
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+\)""")
答案 1 :(得分:1)
我很荣幸在伟大的@MartinOdersky旁边添加一个答案!
从Scala 2.13开始,我们可以使用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)
}
}
代码在Scastie处运行。