Caballero
Caballero

Reputation: 12101

skip N elements in loop whenever condition is met

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

Answers (2)

jwvh
jwvh

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

Tim
Tim

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

Related Questions