【问题标题】:Scala Iterator/Stream with Known Size具有已知大小的 Scala 迭代器/流
【发布时间】:2013-04-29 15:33:33
【问题描述】:

我有一个 Scala Iterator(我可以轻松地使用任何一种数据类型来实现我的目的),它是从 Seq 转换而来的。我想保留它直到我准备好它,但我也希望能够在 O(1) 中获得它的大小。我想知道是否有一种内置的设置方法可以让我保持可迭代对象的迭代器大小。

【问题讨论】:

  • 为什么需要传递迭代器而不是原来的Seq?顺便说一句,你写了 cast... 你不能从 Seq 转换为 Iterator 所以我假设你的意思是 seq.iterator。在我看来,操作迭代器但需要知道大小是有风险的。只要有权访问迭代器的方法调用next(),这将改变迭代器的大小...
  • 如果您正在生成大量数据并打算将其放入Array,我可以看到它很有用。通常的Iterator->Array 路径必须使用可增长的数组,这在渐近上很好,但如果你有大量数据会产生大量垃圾,如果你事先知道大小,那就很不幸了。

标签: scala stream iterator


【解决方案1】:

如果可以支付额外间接的成本,最好将其包装在另一个迭代器中。

class SizedIterator[A](underlying: Iterator[A], val initalSize: Int) extends Iterator[A] {
  def next = underlying.next
  def hasNext = underlying.hasNext
}

然后

new SizedIterator(mySeq.iterator, mySeq.length)

但是请记住,如果您映射或任何新的SizedIterator,您最终将得到一个普通的Iterator,并且不再知道initialSize 有多长。

另外请记住,您不知道消耗了多少迭代器,因此initialSize 是大小的上限,但是当您使用它时,可能没有剩余。

你也可以

mySeq.iterator.zipWithIndex.map{ case (x,i) => (x, mySeq.length-1) }.take(mySeq.length)

生成一个Iterator,它是元素和剩余元素数量的对(包括那个——这样你永远不会达到零)。

如果您只想要在O(1) 中告诉您的已知大小的东西,则将Seq 转换为Iterable.length 方法将与该方法在@ 时一样快地解析987654333@——这是覆盖方法的全部意义——因此不会(通常)每次都使用新的Iterator。但这需要您保留Iterable,而不仅仅是Iterator

【讨论】:

  • @alex23 - 你对迭代器所做的任何事情都可能消耗它(hasNext 除外,next 将只消耗一个元素)。您可以找到大小,但随后什么都没有了(通常——它甚至不承诺,但它不承诺 not 消耗它,这是实现 size 的最简单方法)。你唯一的希望是调用方法,它们本身返回一个你想要的迭代器(它可能只是具有更新状态的同一个迭代器,但这取决于实现来决定),直到你最后一次调用(它产生任何东西,如只要你以你想要的结束)。
  • 我不相信你的SizedIterator 比普通的(Iterator[T], Int) 增加了很多东西……你能说服我吗?
  • @MilesSabin - 它提供的不多。它保留了Iterator[T] 接口,因此您可以在任何需要Iterator[T] 的地方传递它,并再次将其模式匹配以恢复长度,但在尝试编写健壮的代码时通常不建议这样做。我将它作为最接近要求的解决方案提供。我不确定要求其他东西会不会更好!
  • @RexKerr 对于Stream,您建议的解决方案是什么?不能像Iterator一样扩展
  • @MinhThai - 传递一对(Stream, Int)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-04-21
  • 2020-08-03
  • 2021-03-13
  • 1970-01-01
  • 2012-11-11
  • 1970-01-01
  • 2010-12-04
相关资源
最近更新 更多