Scala, repite infinitamente una lista finita.
stream infinite (5)
Aquí hay una implementación que no asume que la length
es eficiente:
def rep[A](seq: Seq[A]) = {
def inner(proj: Seq[A]): Stream[A] = {
if (proj.isEmpty)
inner(seq)
else
Stream.cons(proj.first, inner(proj drop 1))
}
if (seq.isEmpty)
Stream.empty
else
inner(seq)
}
Esto debería ejecutarse en tiempo constante para cualquier Seq
(incluida la List
o incluso Stream
) y solo impone una sobrecarga de tiempo constante para completar cada elemento. Además, funciona incluso para secuencias infinitas. Por lo tanto, puede llamar a rep
en un Stream
infinito y el Stream
resultante será equivalente a la entrada.
Quiero usar la clase Stream en Scala para repetir una lista dada de manera infinita.
Por ejemplo, la lista (1,2,3,4,5) quiero crear una secuencia que me dé (1,2,3,4,5,1,2,3,4,5,1,2,3). ....)
Para que yo pueda envolver la toma de operación. Sé que esto se puede implementar de otras maneras, pero quiero hacerlo de esta manera por alguna razón, solo hazme el humor :)
Entonces, la idea es que con este ciclo infinito creado a partir de alguna lista, puedo usar la operación de toma, y cuando llega al final de la lista, se cicla.
¿Cómo hago una transmisión que simplemente repite una lista dada?
Hay una manera simple con Stream # flatten in scala 2.8
Welcome to Scala version 2.8.0.r20542-b20100116020126 (Java HotSpot(TM) Client VM, Java 1.6.0_18).
Type in expressions to have them evaluated.
Type :help for more information.
scala> def cycle[T](seq: Seq[T]) = Stream.from(0).flatten(_ => seq)
cycle: [T](seq: Seq[T])scala.collection.immutable.Stream[T]
scala> cycle(1::2::3::Nil)
res0: scala.collection.immutable.Stream[Int] = Stream(1, ?)
scala> res0.take(10)
res1: scala.collection.immutable.Stream[Int] = Stream(1, ?)
scala> res0.take(10).toList
res2: List[Int] = List(1, 2, 3, 1, 2, 3, 1, 2, 3, 1)
Muy similar a la de @ Eastsun, pero un poco más reveladora de intenciones. Probado en Scala 2.8.
scala> val l = List(1, 2, 3)
l: List[Int] = List(1, 2, 3)
scala> Stream.continually(l.toStream).flatten.take(10).toList
res3: List[Int] = List(1, 2, 3, 1, 2, 3, 1, 2, 3, 1)
Alternativamente, con Scalaz:
scala> import scalaz._
import scalaz._
scala> import Scalaz._
import Scalaz._
scala> val l = List(1, 2, 3)
l: List[Int] = List(1, 2, 3)
scala> l.toStream.repeat[Stream].join.take(10).toList
res7: List[Int] = List(1, 2, 3, 1, 2, 3, 1, 2, 3, 1)
Robado descaradamente del excelente libro Scala by Example , capítulo 12, y con algunas modificaciones:
def repeatedSeq(idx: Int, lst:Seq[Int]): Stream[Int] = Stream.cons(lst(idx), repeatedSeq((idx + 1)%lst.length, lst))
for(i <- repeatedSeq(1,List(1,1,2,3,5))) println(i)
Esto funciona para todos los tipos de secuencias (a menos que no puedan leerse varias veces, por supuesto). Podría no ser eficiente si la llamada .length es lenta. Probado en Scala 2.7.7.
Un método alternativo es concatenar el .toStream
de la entrada consigo mismo recursivamente. Es decir,
scala> val xs: Stream[Int] = List(1, 2, 3).toStream #::: xs
xs: Stream[Int] = Stream(1, ?)
scala> xs.take(10).toList
res1: List[Int] = List(1, 2, 3, 1, 2, 3, 1, 2, 3, 1)