问题
How to split an iterator into a prefix with duplicates and the rest ? For instance,
def splitDupes(it: Iterator[Int]): (Iterator[Int], Iterator[Int]) = ???
val (xs, ys) = splitDupes(List(1, 1, 1, 2, 3, 4, 5).iterator)
xs.toList // List(1, 1, 1)
ys.toList // List(2, 3, 4, 5)
val (xs, ys) = splitDupes(List(1, 2, 3, 4, 5).iterator)
xs.toList // List(1)
ys.toList // List(2, 3, 4, 5)
val (xs, ys) = splitDupes(List(1, 1, 1, 1, 1).iterator)
xs.toList // List(1, 1, 1, 1, 1)
ys.toList // List()
val (xs, ys) = splitDupes(List[Int]().iterator)
xs.toList // List()
ys.toList // List()
Can I use it to read a text file by chunks ?
回答1:
You can use the span method to split an Iterable into a prefix that satisfies a predicate and a suffix that doesn't. For Iterators span does the correct thing, and lazily stores elements in the prefix Iterator, in case the suffix was iterated before the prefix has run out.
def splitDupes[T](it: Iterator[T]): (Iterator[T], Iterator[T]) = {
  if (it.isEmpty) (Iterator.empty, Iterator.empty)
  else {
    val head = it.next()
    val (dupes, rest) = it.span(_ == head)
    (Iterator(head) ++ dupes, rest)
  }
}
Example:
scala> val (dupes, rest) = splitDupes(Iterator(1,1,1,2,3,2,1))
dupes: Iterator[Int] = <iterator>
rest: Iterator[Int] = <iterator>
scala> (dupes.toList, rest.toList)
res1: (List[Int], List[Int]) = (List(1, 1, 1),List(2, 3, 2, 1))
回答2:
What about something like this?
(Note: I decided to return a plain List as the first part since that would already been consumed)
def splitDupes[A](it: Iterator[A]): (List[A], Iterator[A]) = {
  it.nextOption() match {
    case Some(head) =>
      @annotation.tailrec
      def loop(count: Int): (List[A], Iterator[A]) =
        it.nextOption() match {
          case Some(x) if (x == head) =>
            loop(count + 1)
          case Some(x) =>
            List.fill(count)(head) -> Iterator(Iterator.single(x), it).flatten
          case None =>
            List.fill(count)(head) -> Iterator.empty
        }
      loop(count = 1)
    case None =>
      List.empty -> Iterator.empty
  }
}
来源:https://stackoverflow.com/questions/59142798/how-to-split-up-an-iterator