Слишком низкий уровень. Но это гарантирует, что он будет потреблять элементы только по мере необходимости.
def remove[A](it: Iterator[A]): Iterator[A] =
new Iterator[A] {
private[this] var current: Option[A] = None
override def hasNext: Boolean =
it.hasNext || (current ne None)
override def next(): A = {
@annotation.tailrec
def loop(): A = (it.nextOption(), current) match {
case (Some(a), Some(c)) if (a == c) =>
loop()
case (sa @ Some(a), Some(c)) =>
current = sa
c
case (sa @ Some(a), None) =>
current = sa
loop()
case (None, Some(c)) =>
current = None
c
case (None, None) =>
Iterator.empty[A].next()
}
loop()
}
}
Более или менее так же, как указано выше, но вместо этого используется unfold
.
def remove[A](it: Iterator[A]): Iterator[A] = {
type State = (Option[A], Option[A]) // value -> current
def process(state: State): Option[State] = state match {
case (Some(a), sc @ Some(c)) if (a == c) =>
Some(None -> sc)
case (sa @ Some(a), sc @ Some(c)) =>
Some(sc -> sa)
case (sa @ Some(a), None) =>
Some(None -> sa)
case (None, sc @ Some(c)) =>
Some(sc -> None)
case (None, None) =>
None
}
Iterator.unfold(it.nextOption() -> Option.empty[A]) { state =>
process(state).map {
case (value, current) =>
(value -> (it.nextOption() -> current))
}
} collect {
case Some(a) => a
}
}
(их можно сделать более эффективными, используя null
вместо Option , но это требует специальной обработки примитивов)