如何折叠Scala迭代器并获得延迟计算的序列作为结果?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何折叠Scala迭代器并获得延迟计算的序列作为结果?相关的知识,希望对你有一定的参考价值。
我有一个字符串迭代器,其中每个字符串可以是"H"
(标题)或"D"
(详细信息)。我想将此迭代器拆分为多个块,其中每个块均以一个标头开头,并且可以具有0到许多详细信息。
我知道如何解决将所有内容加载到内存中的问题。例如,下面的代码:
Seq("H","D","D","D","H","D","H","H","D","D","H","D").toIterator
.foldLeft(List[List[String]]())((acc, x) => x match
case "H" => List(x) :: acc
case "D" => (x :: acc.head) :: acc.tail )
.map(_.reverse)
.reverse
返回5个块-List(List(H, D, D, D), List(H, D), List(H), List(H, D, D), List(H, D))
-这是我想要的。
但是,我想要List[List[String]]
而不是结果中的Iterator[List[String]]
或某种其他结构,让我可以懒惰地评估结果,并且如果整个迭代器都被消耗,则不要将整个输入加载到内存中 ,我只想一次仅将正在消耗的块加载到内存中(例如:当我调用iterator.next
时)。
如何修改上面的代码以获得所需的结果?
编辑:我特别需要在Scala 2.11中使用它,因为我使用的是它所遵循的环境。很高兴也接受其他版本的答案。
答案
如果使用Scala 2.13.x,则可以通过展开原始Iterator
来创建新的Iterator
。>
import scala.collection.mutable.ListBuffer val data = Seq("H","D","D","D","H","D","H","H","D","D","H","D").iterator val rslt = Iterator.unfold(data.buffered)itr => if (itr.hasNext) val lb = ListBuffer(itr.next()) while (itr.hasNext && itr.head == "D") lb += itr.next() Some((lb.toList, itr)) else None
测试:
rslt.next() //res0: List[String] = List(H, D, D, D)
rslt.next() //res1: List[String] = List(H, D)
rslt.next() //res2: List[String] = List(H)
rslt.next() //res3: List[String] = List(H, D, D)
rslt.next() //res4: List[String] = List(H, D)
rslt.hasNext //res5: Boolean = false
以上是关于如何折叠Scala迭代器并获得延迟计算的序列作为结果?的主要内容,如果未能解决你的问题,请参考以下文章
迭代 RDD 迭代器并应用限制时,Spark 似乎没有调用 hasNext
java - 如何在java中的map上保留两个迭代器并在没有ConcurrentModificationException的情况下删除它们之间的键