Предположим, я пишу функцию foo: Iterator[A] => Iterator[List[A]]
для преобразования заданного итератора в итератор кусков дубликатов:
def foo[T](it: Iterator[A]): Iterator[List[A]] = ???
foo("abbbcbbe".iterator).toList.map(_.mkString) // List("a", "bbb", "c", "bb", "e")
Для реализации foo
Я хочу использовать функцию splitDupes: Iterator[A] => (List[A], Iterator[A])
, которая разбивает итератор на префикс с дубликатами и остальным (большое спасибо Колмару , который предложил это здесь )
def splitDupes[A](it: Iterator[A]): (List[A], Iterator[A]) = {
if (it.isEmpty) {
(Nil, Iterator.empty)
} else {
val head = it.next
val (dupes, rest) = it.span(_ == head)
(head +: dupes.toList, rest)
}
}
Теперь я пишу foo
используя splitDupes
вот так:
def foo[A](it: Iterator[A]): Iterator[List[A]] = {
if (it.isEmpty) {
Iterator.empty
} else {
val (xs, ys) = Iterator.iterate(splitDupes(it))(x => splitDupes(x._2)).span(_._2.nonEmpty)
(if (ys.hasNext) xs ++ Iterator(ys.next) else xs).map(_._1)
}
}
Эта реализация кажется работающей, но выглядит сложной и неуклюжей.
Как бы вы улучшили реализацию foo
выше?