如何在 Scala 中简短地编写“过滤满足给定函数的第一个/最后 n 个元素”?

use*_*663 2 scala

如何在 Scala 中快速编写“过滤掉满足给定函数的序列的第一个/最后 n 个元素”?

FilterNot 定义为:

def filterNot(p: A => Boolean): Repr
Run Code Online (Sandbox Code Playgroud)

所以我正在寻找这样的功能:

def filterNotFirst(p: A => Boolean, n: Int): Repr
Run Code Online (Sandbox Code Playgroud)

最好是这样太大的 n 不会抛出异常。

Tra*_*own 6

Scala 集合库没有提供完全执行此操作的操作,但有一种惯用的编写方式:组合filterfilterNottaketakeRight

scala> val elems: Seq[Int] = 0 to 100
elems: Seq[Int] = Range 0 to 100

scala> elems.filterNot(_ < 10).take(5)
res0: Seq[Int] = Vector(10, 11, 12, 13, 14)

scala> elems.filterNot(_ < 10).takeRight(5)
res1: Seq[Int] = Vector(96, 97, 98, 99, 100)
Run Code Online (Sandbox Code Playgroud)

如果n大于可用值的数量,则不会抛出异常:

scala> (0 to 15).filterNot(_ < 10).take(100)
res3: IndexedSeq[Int] = Vector(10, 11, 12, 13, 14, 15)
Run Code Online (Sandbox Code Playgroud)

如果你真的想要filterNotFirst一个方法,你可以自己定义它:

def filterNotFirst[A](elems: Seq[A])(p: A => Boolean, n: Int): Seq[A] =
  elems.filterNot(p).take(n)
Run Code Online (Sandbox Code Playgroud)

甚至:

scala> implicit class FilterNotFirstOp[A](elems: Seq[A]) {
     |   def filterNotFirst(p: A => Boolean, n: Int): Seq[A] =
     |     elems.filterNot(p).take(n)
     | }
defined class FilterNotFirstOp
Run Code Online (Sandbox Code Playgroud)

进而:

scala> (0 to 15).filterNotFirst(_ < 10, 100)
res4: Seq[Int] = Vector(10, 11, 12, 13, 14, 15)
Run Code Online (Sandbox Code Playgroud)

我只是使用建议filterNot,并take在需要的地方,虽然。