Transforming an iterator into an iterator of chunks of duplicates

耗尽温柔 提交于 2021-01-28 13:47:03

问题


Suppose I am writing a function foo: Iterator[A] => Iterator[List[A]] to transform a given iterator into an iterator of chunks of duplicates :

def foo[T](it: Iterator[A]): Iterator[List[A]] = ???
foo("abbbcbbe".iterator).toList.map(_.mkString) // List("a", "bbb", "c", "bb", "e")

In order to implement foo I want to reuse function splitDupes: Iterator[A] => (List[A], Iterator[A]) that splits an iterator into a prefix with duplicates and the rest (thanks a lot to Kolmar who suggested it here)

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)
  }
}

Now I am writing foo using splitDupes like that:

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)
   }
}

This implementation seems working but it's look complicated and clumsy.
How would you improve the foo implementation above ?


回答1:


You can do it like this:

def foo[A](it: Iterator[A]): Iterator[List[A]] = {
  Iterator.iterate(splitDupes(it))(x => splitDupes(x._2))
    .map(_._1)
    .takeWhile(_.nonEmpty)
}

The empty case is already handled in splitDupes. You can safely keep calling splitDupes until it hits this empty case (that is, starts returning Nil in the first tuple element).

This works ok in all cases:

scala> foo("abbbcbbe".iterator).toList.map(_.mkString)
res1: List[String] = List(a, bbb, c, bb, e)

scala> foo("".iterator).toList.map(_.mkString)
res2: List[String] = List()

scala> foo("a".iterator).toList.map(_.mkString)
res3: List[String] = List(a) 

scala> foo("aaa".iterator).toList.map(_.mkString)
res4: List[String] = List(aaa)

scala> foo("abc".iterator).toList.map(_.mkString)
res5: List[String] = List(a, b, c)


来源:https://stackoverflow.com/questions/60025718/transforming-an-iterator-into-an-iterator-of-chunks-of-duplicates

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