我对特征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 项?
答案 0 :(得分:10)
有问题的迭代器在IndexedSeqLike#Elements
(source)中定义。关于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
无法进一步使用 - 在行为未定义且可能发生变化的意义上无用。