Reputation: 15569
I'd like to remove only the few last elements of a List
(or Seq
), and avoid parsing all elements (and avoid applying the filter function to all of them).
Let's say, for example, I have a random strictly increasing list of values:
import scala.util.Random.nextInt
val r = (1 to 100).map(_ => nextInt(10)+1).scanLeft(0)(_+_)
And I want to remove the elements greater than, say, 300. I can do this like that:
r.filter(_<300)
but this method parse the whole list. So, is it possible to filter a list only on one end? Something like a filterRight
method?
subquestions:
List
/Seq
, what about IndexedSeq
like Vector
or Array
Solutions
I selected @elm solution because it answers the subquestion for general list, not only (strictly) increasing ones. However, the solution of @dcastro looks to be more efficient as it doesn't do 2 reverse
Upvotes: 1
Views: 437
Reputation: 20435
First note SI-4247 on dropWhile but no dropRightWhile.
Though, a simple implementation that conveys the desired semantics,
def dropRightWhile[A](xs: Seq[A], p: A => Boolean) =
xs.reverse.dropWhile(p).reverse
or equivalently
implicit class OpsSeq[A](val xs: Seq[A]) extends AnyVal {
def dropRightWhile(p: A => Boolean) = xs.reverse.dropWhile(p).reverse
}
Upvotes: 2
Reputation: 68750
You're looking for something like dropRightWhile
, which doesn't exist in the standard library (but has been requested before).
I think your best bet is:
r.takeWhile(_<300)
Since it's an increasing list of values, you can stop performing any checks when you first encounter an element greater than 300
Upvotes: 2