How to split up an Iterator?

情到浓时终转凉″ 提交于 2021-02-04 16:37:23

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!