Reputation: 12101
Is there a straightforward idiomatic way, maybe even existing method to accomplish this in scala:
Perform a loop/iterator checking every element in a sequence against a condition. Whenever the condition is met, skip the next N elements, then continue checking the rest until condition is met again, skip N elements and so on.
The only way I thought of is to use a mutable counter or a tail recursion. Is there a better solution?
Upvotes: 2
Views: 203
Reputation: 51271
I'm surprised nobody has mentioned unfold()
(Scala 2.13.x).
def select[A](input: List[A], test: A=>Boolean, skipN: Int): List[A] =
List.unfold(input){ lst =>
Option.when(lst.nonEmpty){
if (test(lst.head)) (lst.head, lst.tail.drop(skipN))
else (lst.head, lst.tail)
}
}
In this version, every element that is tested for "a condition" is an element of the result, the skipped elements are (of course) not.
Upvotes: 5
Reputation: 27356
A recursive routine is the right way to go, something like this:
def filterSkip[T](list: List[T], f: T => Boolean, skip: Int): List[T] = {
@annotation.tailrec
def loop(l: List[T], res: List[T]): List[T] =
l match {
case Nil => res.reverse
case hd::tail =>
if (f(hd)) {
loop(tail.drop(skip), res)
} else {
loop(tail, hd +: res)
}
}
loop(list, Nil)
}
This version drops the matching element and N following elements, but it could be easily modified to retain the matching element if required.
Upvotes: 1