Ho bisogno di scorrere attraverso un elenco ma modo circolare. Ho anche bisogno di aggiungere nuovi elementi alla lista e scorrere tutti gli elementi (vecchi e nuovi elementi), come faccio? C'è qualche struttura dati per loro?Iterating circular way
risposta
Penso che forse questo è quello che vuoi; la possibilità di aggiungere nuovi elementi alla tua lista anche mentre la stai iterando. Il codice è brutto ma sembra funzionare.
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
}
Si può usare in questo modo:
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)
Una possibilità è quella di utilizzare la classe Stream
per creare un pigro, circolare, sequenza infinita:
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)
o in questo modo:
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
Questo genere di cose merita davvero di essere nella norma libreria di flusso, ma non sembra essere. La risposta di dbryne con un flusso funziona bene, o se preferite in for-comprensione forma
val listToRepeat:List[Foo]
val forever:Stream[Foo] = for(x<-Stream.continually(1); y<-listToRepeat) yield y
Il primo generatore di flusso mantiene le cose andare per sempre, anche se si sta ignorando il valore. Il secondo generatore viene implicitamente appiattito nel flusso infinito desiderato.
Non hai bisogno di un argomento per' Stream.continually() ', penso che l'uso di un 'Stream [Unit]' sembra un po' meno confuso di un 'Stream [Int] '. – Debilski
def forever:Stream[Int] = Stream(1,2,3) append forever
Nota questo è infinito, ma non circolare. –
i flussi sono infiniti, ma non sono circolari. Per renderli circolari è necessario un trucco come 'def circular [T] (xs: Stream [T]): Stream [T] = {lazy val knot: Stream [T] = xs # ::: knot; knot} ' –