List
已经有一个slice
方法 - 它采用开始索引和结束索引之间的元素子集。您正在寻找的是重复应用span
method:
def span(p: (A) ⇒ Boolean): (List[A], List[A])
其记录为:
根据谓词将此列表拆分为前缀/后缀对。
注意:c span p 相当于(但可能比)(c takeWhile p, c dropWhile p) 更有效,前提是谓词 p 的计算不会引起任何副作用。
returns:由该列表中元素全部满足 p 的最长前缀和该列表的其余部分组成的对。
您可以通过重复使用此方法和逆谓词来获得所需的内容,并使用额外的逻辑来确保返回的列表都不为空。
import annotation.tailrec
def multiSpan[A](xs: List[A])(splitOn: (A) => Boolean): List[List[A]] = {
@tailrec
def loop(xs: List[A], acc: List[List[A]]) : List[List[A]] = xs match {
case Nil => acc
case x :: Nil => List(x) :: acc
case h :: t =>
val (pre,post) = t.span(!splitOn(_))
loop(post, (h :: pre) :: acc)
}
loop(xs, Nil).reverse
}
UPDATE
根据原始帖子评论中的要求,这里有一个丰富列表的版本,而不是一个独立的方法:
implicit class AddMultispanToList[A](val list: List[A]) extends AnyVal {
def multiSpan(splitOn: (A) => Boolean): List[List[A]] = {
@tailrec
def loop(xs: List[A], acc: List[List[A]]) : List[List[A]] = xs match {
case Nil => acc
case x :: Nil => List(x) :: acc
case h :: t =>
val (pre,post) = t.span(!splitOn(_))
loop(post, (h :: pre) :: acc)
}
loop(list, Nil).reverse
}
}
Use as:
myList.multiSpan(_.isInstanceOf[TypeA])