I need iterate through a List but circular way. I need too add new elements to the list and iterate over all elements (olds and news elements), How I do it? Is there any dat
def forever:Stream[Int] = Stream(1,2,3) append forever
This sort of thing really deserves to be in standard stream library, but doesn't appear to be. dbryne's answer with a stream works well, or if you prefer it in for-comprehension form
val listToRepeat:List[Foo]
val forever:Stream[Foo] = for(x<-Stream.continually(1); y<-listToRepeat) yield y
The first stream generator keeps things going forever even though you are ignoring the value. The second generator gets implicitly flattened into the infinite stream you want.
One option is to use the Stream
class to create a lazy, circular, infinite sequence:
scala> val values = List(1, 2, 3)
values: List[Int] = List(1, 2, 3)
scala> Stream.continually(values.toStream).flatten.take(9).toList
res2: List[Int] = List(1, 2, 3, 1, 2, 3, 1, 2, 3)
or this way:
val values = List(1, 2, 3)
def circularStream(values: List[Int],
remaining: List[Int] = List()): Stream[Int] = {
if (remaining.isEmpty)
circularStream(values,values)
else
Stream.cons(remaining.head, circularStream(values, remaining.drop(1)))
}
circularStream(values).take(9).toList //Same result as example #1
I think maybe this is what you want; the ability to add new elements to your list even as you are iterating it. The code is ugly but it seems to work.
import scala.collection.mutable.Queue
class Circular[A](list: Seq[A]) extends Iterator[A]{
val elements = new Queue[A] ++= list
var pos = 0
def next = {
if (pos == elements.length)
pos = 0
val value = elements(pos)
pos = pos + 1
value
}
def hasNext = !elements.isEmpty
def add(a: A): Unit = { elements += a }
override def toString = elements.toString
}
You can use it like this:
scala> var circ = new Circular(List(1,2))
res26: Circular[Int] = Queue(1,2)
scala> circ.next
res27: Int = 1
scala> circ.next
res28: Int = 2
scala> circ.next
res29: Int = 1
scala> circ.add(5)
scala> circ.next
res30: Int = 2
scala> circ.next
res31: Int = 5
scala> circ
res32: Circular[Int] = Queue(1,2,5)