使用scala迭代器中的项目

时间:2011-10-01 10:25:14

标签: scala iterator scala-collections

我对特征take中方法Iterator的行为感到困惑。它似乎不消耗物品。这是一个例子:

scala> Iterator(1,2,3)
res0: Iterator[Int] = non-empty iterator

scala> res0 take 2 toArray
res1: Array[Int] = Array(1, 2)

scala> res0.next
res2: Int = 1

显然,第2步消耗两项,但在第3步中,Iterator仍然是第一项。看看实现,我看不到任何类型的复制或缓冲,只是一个新的Iterator代表底层的。怎么可能呢?如何才能真正使用 n 项?

3 个答案:

答案 0 :(得分:10)

有问题的迭代器在IndexedSeqLike#Elementssource)中定义。关于take在不同迭代器实现中的不一致行为的ticket was recently filed

要真正消耗N个项目,请拨打Iterator#next N次。

您可能需要考虑使用Stream,这是一个懒惰的(如Iterator),但也是不可变的(与Iterator不同)。

scala> val s = Stream(1, 2, 3)
s: scala.collection.immutable.Stream[Int] = Stream(1, ?)

scala> s.take(2).toList
res43: List[Int] = List(1, 2)

scala> s.take(2).toList
res44: List[Int] = List(1, 2)

scala> s.drop(2).toList
res45: List[Int] = List(3)

scala> {val (s1, s2) = s.splitAt(2); (s1.toList, s2.toList)}
res46: (List[Int], List[Int]) = (List(1, 2),List(3))

答案 1 :(得分:2)

谢谢你们。

这是我使用Iterator

消耗一串项目的解决方案
  implicit def consumable(i: Iterator[_]) = new {
    def next(n: Int) = {
      (for (_ <- 1 to n) yield i.next()).iterator
    }
    def skip(n: Int) {
      (1 to n).foreach(_ => i.next())
    }
  }

欢迎任何评论。

答案 2 :(得分:1)

您想要使用这些项目drop。请注意,调用Iterator的大多数方法都会使Iterator无法进一步使用 - 在行为未定义且可能发生变化的意义上无用。