elm*_*elm 2 collections scala list slice
对于
trait Item
case class TypeA(i: Int) extends Item
case class TypeB(i: Int) extends Item
Run Code Online (Sandbox Code Playgroud)
考虑一个Scala项目列表,例如
val myList = List(TypeA(1), TypeB(11), TypeB(12),
TypeA(2), TypeB(21),
TypeA(3), TypeB(31))
Run Code Online (Sandbox Code Playgroud)
目的是定义一个新slice
方法,该方法可以应用到myList
谓词或条件作为参数。例如
myList.slice { x => x.isInstanceOf[TypeA] }
Run Code Online (Sandbox Code Playgroud)
会提供
List(List(TypeA(1), TypeB(11), TypeB(12)),
List(TypeA(2), TypeB(21)),
List(TypeA(3), TypeB(31)))
Run Code Online (Sandbox Code Playgroud)
在此示例中,将通过以下方式获得相同的结果
myList.slice { case TypeA(x) => x < 10 }
Run Code Online (Sandbox Code Playgroud)
非常感谢。
List
已经有一个slice
方法-它需要在开始索引和结束索引之间包含元素的子集。您正在寻找的是该span
方法的重复应用:
def span(p: (A) ? Boolean): (List[A], List[A])
Run Code Online (Sandbox Code Playgroud)
记录为:
根据谓词将此列表拆分为前缀/后缀对。
注意:如果对谓词p的求值不会引起任何副作用,则c span p等效于(但可能比p更有效)。
返回:一对,该列表的所有元素都满足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
}
Run Code Online (Sandbox Code Playgroud)
更新
根据原始帖子的评论要求,这是一个丰富列表而不是独立方法的版本:
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
}
}
Run Code Online (Sandbox Code Playgroud)
用于:
myList.multiSpan(_.isInstanceOf[TypeA])
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
716 次 |
最近记录: |