将迭代器转换为重复块的迭代器 [英] Transforming an iterator into an iterator of chunks of duplicates
问题描述
假设我正在编写函数foo: Iterator[A] => Iterator[List[A]]
,将给定的迭代器转换为重复块的迭代器:
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")
为了实现foo
,我想重用函数splitDupes: Iterator[A] => (List[A], Iterator[A])
,该函数将迭代器拆分为具有重复项和其余部分的前缀(非常感谢此处提出了建议)
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)
}
}
现在我正在使用splitDupes
这样写foo
:
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)
}
}
此实现似乎可以正常工作,但看起来又复杂又笨拙.
您如何改善上述foo
实施?
This implementation seems working but it's look complicated and clumsy.
How would you improve the foo
implementation above ?
推荐答案
您可以这样做:
def foo[A](it: Iterator[A]): Iterator[List[A]] = {
Iterator.iterate(splitDupes(it))(x => splitDupes(x._2))
.map(_._1)
.takeWhile(_.nonEmpty)
}
空案例已在splitDupes
中处理.您可以放心地继续调用splitDupes
,直到遇到空的情况为止(也就是说,开始在第一个元组元素中返回Nil
).
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)
这篇关于将迭代器转换为重复块的迭代器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!