如何在scala中使用迭代器高效地基于内存长度做出决策

如何在scala中使用迭代器高效地基于内存长度做出决策,scala,iterator,Scala,Iterator,我有一个很长的集合,我需要在scala中迭代,我希望避免将其全部保存在内存中。我提出的解决方案是: (rows是我试图处理的迭代器,COMPONENT_限制了我可以在内存中保存多少个计算对象的估计值) 我的问题是:尽管我不再需要使用pastLimitItr,但从队列中可以看出,它将挂起,因此使用的内存将与迭代器的长度相关 问题是:在完成测试后,如何在def duplicate中除去Partner对象中的队列?考试后我根本不需要复印件 更新:我应该添加输出迭代器对象将根据其内容包含输入迭代器中的一

我有一个很长的集合,我需要在scala中迭代,我希望避免将其全部保存在内存中。我提出的解决方案是:

(rows是我试图处理的迭代器,COMPONENT_限制了我可以在内存中保存多少个计算对象的估计值)

我的问题是:尽管我不再需要使用pastLimitItr,但从队列中可以看出,它将挂起,因此使用的内存将与迭代器的长度相关

问题是:在完成测试后,如何在def duplicate中除去Partner对象中的队列?考试后我根本不需要复印件

更新:我应该添加输出迭代器对象将根据其内容包含输入迭代器中的一些对象,因此我不能使用建议的分组


更新:在答案中给出的选项中,span似乎是正确的答案。我的问题可能不够具体。

听起来您想使用:

val segments = iterator.grouped(LIMIT)
createObject(segments.next())
如果确实需要
副本
,您可以将副本排空

您还可以将
迭代器.span
与计数条件一起使用:

scala> val it = (1 to 10).iterator
it: Iterator[Int] = non-empty iterator

scala> var n = 0 ; val (vs, rest) = it.span { _ => n += 1; n < 3 }
n: Int = 0
vs: Iterator[Int] = non-empty iterator
rest: Iterator[Int] = unknown-if-empty iterator

scala> vs.toList
res0: List[Int] = List(1, 2)

scala> rest.toList
res1: List[Int] = List(3, 4, 5, 6, 7, 8, 9, 10)
但是我看到您实际上想要使用前缀或剩余的迭代器

我会编写一个自定义方法。或者不要笑:

scala> val (is, rest) = (1 to 10).iterator.splitAt(6)
is: Iterator[Int] = non-empty iterator
rest: Iterator[Int] = unknown-if-empty iterator

scala> is match { case it: collection.Iterator$Leading$1 if rest.hasNext => it.finish() ; rest ; case _ => is }
res6: Iterator[Int] = unknown-if-empty iterator

scala> res6.next
res7: Int = 7
内部
finish
意味着您可以在不缓冲前缀的情况下使用
rest

您还可以在实现时作弊
分组
,并将原始迭代器用于
rest

scala> val it = (1 to 10).iterator
it: Iterator[Int] = non-empty iterator

scala> val g = it.grouped(3)
g: it.GroupedIterator[Int] = non-empty iterator

scala> val first = g.next
first: List[Int] = List(1, 2, 3)

scala> it.hasNext
res12: Boolean = true

scala> it.next
res13: Int = 4
无需保留内部构件的自定义方法:

scala> :pa
// Entering paste mode (ctrl-D to finish)

implicit class splitItAt[A](private val it: Iterator[A]) extends AnyVal {
  def splitAt(i: Int): (List[A], Iterator[A]) = {
    val buf = mutable.ListBuffer.empty[A]
    var n = 0
    while (it.hasNext && n < i) {
      buf += it.next()
      n += 1
    }
    (buf.toList, it)
  }
}

// Exiting paste mode, now interpreting.

defined class splitItAt

scala> val (is, rest) = (1 to 10).iterator.splitAt(20)
is: List[Int] = List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
rest: Iterator[Int] = empty iterator

scala> val (is, rest) = (1 to 10).iterator.splitAt(6)
is: List[Int] = List(1, 2, 3, 4, 5, 6)
rest: Iterator[Int] = non-empty iterator

scala> val (is, rest) = (1 to 10).iterator.splitAt(0)
is: List[Int] = List()
rest: Iterator[Int] = non-empty iterator
scala>:pa
//进入粘贴模式(按ctrl-D键完成)
隐式类splitItAt[A](私有值it:Iterator[A])扩展了AnyVal{
def splitAt(i:Int):(列表[A],迭代器[A])={
val buf=mutable.ListBuffer.empty[A]
var n=0
while(it.hasNext&&nval(is,rest)=(1到10).iterator.splitAt(20)
is:List[Int]=List(1,2,3,4,5,6,7,8,9,10)
rest:Iterator[Int]=空迭代器
scala>val(is,rest)=(1到10).迭代器.splitAt(6)
is:List[Int]=List(1,2,3,4,5,6)
rest:Iterator[Int]=非空迭代器
scala>val(is,rest)=(1到10).iterator.splitAt(0)
is:List[Int]=List()
rest:Iterator[Int]=非空迭代器

谢谢。我不能使用分组方法,因为分段不是固定长度的。我可能可以使用span,我将研究它。输入->输出将如下所示:
迭代器(SomeObject(2,…),SomeObject(2,…),SomeObject(2,…),SomeObject(3,…),SomeObject(3,…),SomeObject(3,…)
应该给出
迭代器(ObjectsOf(2,List(SomeObject(2,…),SomeObject(2,…)),ObjectsOf(3,List)(SomeObject(3,…),SomeObject(3,…),SomeObject(3,…),…)
那种习语,
groupWhile
,已经在ML上讨论过了,但我找不到。基本上,你自己写就行了。类似的情绪Ok span是我想问的问题的正确答案。我不确定我的问题是否已经说得足够清楚。(当然,为了给出你在评论中看到的输出,我有一个自定义迭代器)好吧,这更多的是旅程而不是目的地。
scala> val it = (1 to 10).iterator
it: Iterator[Int] = non-empty iterator

scala> val g = it.grouped(3)
g: it.GroupedIterator[Int] = non-empty iterator

scala> val first = g.next
first: List[Int] = List(1, 2, 3)

scala> it.hasNext
res12: Boolean = true

scala> it.next
res13: Int = 4
scala> :pa
// Entering paste mode (ctrl-D to finish)

implicit class splitItAt[A](private val it: Iterator[A]) extends AnyVal {
  def splitAt(i: Int): (List[A], Iterator[A]) = {
    val buf = mutable.ListBuffer.empty[A]
    var n = 0
    while (it.hasNext && n < i) {
      buf += it.next()
      n += 1
    }
    (buf.toList, it)
  }
}

// Exiting paste mode, now interpreting.

defined class splitItAt

scala> val (is, rest) = (1 to 10).iterator.splitAt(20)
is: List[Int] = List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
rest: Iterator[Int] = empty iterator

scala> val (is, rest) = (1 to 10).iterator.splitAt(6)
is: List[Int] = List(1, 2, 3, 4, 5, 6)
rest: Iterator[Int] = non-empty iterator

scala> val (is, rest) = (1 to 10).iterator.splitAt(0)
is: List[Int] = List()
rest: Iterator[Int] = non-empty iterator