Reputation: 15355
I wanted to create n iterators from one in scala using 'duplicate'
came up with that code:
def getNIterators[T](it: Iterator[T], n: Int) : Seq[Iterator[T]] = {
getNMoreIterators(Seq(it), n-1)
}
private def getNMoreIterators[T](seq: Seq[Iterator[T]], n: Int) : Seq[Iterator[T]] = {
if (n <= 0) return seq else {
val (it1, it2) = seq.head.duplicate
Seq(it1, it2) ++ getNMoreIterators(seq.tail, n-1)
}
}
Can I improve it to tailrecurtion or a method that is more efficient?
Upvotes: 0
Views: 270
Reputation: 8663
You are actually destroying the current Iterator
and getting 2 new in return. I think it would me more efficient to just destroy Iterator
once and put it in a Seq
, getting iterators from there (that's just an intuition, I didn't bemchmark it).
def getNIterators[A](it: Iterator[A], n: Int) : Seq[Iterator[A]] = {
val seq = it.toSeq
Seq.fill(n)(seq.iterator)
}
You might want to read about problems with duplicate
here: How to copy iterator in Scala? and here: How to clone an iterator?
Ok then, if you don't want to consume whole iterator in the beginning, consider using a Stream
def getNIterators[A](it: Iterator[A], n: Int) : Seq[Iterator[A]] = {
val seq = it.toStream
Seq.fill(n)(seq.iterator)
}
It will consume Iterator
as needed (except for the head, it will be consumed immidietly), and all the Iterators
are independent.
scala> (1 to 4).iterator.map(s => {println(s); s})
res12: Iterator[Int] = non-empty iterator
scala> getNIterators(res12, 4)
1
res13: Seq[Iterator[Int]] = List(non-empty iterator, non-empty iterator, non-empty iterator, non-empty iterator)
scala> res13.map(_.next)
res14: Seq[Int] = List(1, 1, 1, 1)
scala> res13.map(_.next)
2
res15: Seq[Int] = List(2, 2, 2, 2)
scala> res13.map(_.next)
3
res16: Seq[Int] = List(3, 3, 3, 3)
scala> res13.map(_.next)
4
res17: Seq[Int] = List(4, 4, 4, 4)
Upvotes: 1
Reputation: 37822
How about:
def getNIterators[T](it: Iterator[T], n: Int) : Seq[Iterator[T]] = {
(1 to n).map(_ => it.duplicate._2)
}
Upvotes: 0