2010-01-19 8 views
26

Quiero usar la clase Stream en scala para repetir una lista dada infinitamente.Scala, repita una lista finita infinitamente

Por ejemplo, la lista (1,2,3,4,5) Quiero crear una secuencia que me da (1,2,3,4,5,1,2,3,4,5,1 , 2,3 ....)

Para que pueda ajustar la operación de toma. Sé que esto se puede implementar de otras maneras, pero quiero hacerlo de esta manera por alguna razón, solo me pones de humor :)

Así que la idea es que con este ciclo infinito creado a partir de alguna lista, pueda usar Take Operation, y cuando llega al final de la lista, se cicla.

¿Cómo hago una secuencia que simplemente repite una lista dada?

Respuesta

33

muy similar a la de @ Eastsun, pero un poco más intención reveladora. 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) 
+1

Me gustó esta respuesta lo mejor, continuamente en el objeto compañero de Stream es realmente lo que estaba buscando. También combinado con flatten y tolist obtengo exactamente lo que quiero :) BTW, somestream.join.take (10) .toList, ¿alguien puede explicar la necesidad de la notación object.function() y por qué es necesaria aquí? Usualmente puede tener "seq take 10", y algo como "seq take 10.toList" ¿funcionaría? – Felix

+0

Creo que vale la pena señalar que "Stream.continually()" aparentemente no estaba presente en versiones anteriores de 2.8 – Felix

+0

En 2.7, 'Stream.continually' era' Stream.const' y 'streams.flatten' era' Stream.concat (transmisiones) ' – retronym

1

robados blatently 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 SEQ (a menos que no se pueden leer varias veces, por supuesto). Puede que no sea eficiente si la llamada .length es lenta. Probado en Scala 2.7.7.

+2

"a menos que no se pueden leer varias veces, por supuesto" Pero cuando se habla acerca de las secuencias, siempre se debe asumir que este es el caso. –

5

Aquí es una implementación que no asumen que 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 funcionar en un tiempo constante para cualquier Seq (incluyendo List o incluso Stream) y sólo impone una sobrecarga constante de tiempo para rellenar cada uno elemento. Además, funciona incluso para secuencias infinitas. Entonces, puede llamar al rep en un Stream infinito y el Stream resultante será equivalente a la entrada.

7

Hay una manera sencilla con la corriente # aplanan en 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) 
+1

Interesante. ¿Cómo funciona? –

+0

Stream.from (0) es solo para proporcionar un flujo infinito de objetos: cualquier otra secuencia infinita de objetos de cualquier tipo funcionaría. A continuación, llama a flatten (asTraversable) para convertir cada objeto (sin importar lo que sea) en una secuencia. En este caso, asTraversable convierte el objeto en la secuencia original seq. Es una forma interesante de hacer seq ++ seq ++ seq ... –

22

Un método alternativo es la concatenación de los .toStream de la entrada con sí mismo de forma recursiva. 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) 
+2

Creo que este es el mejor enfoque, ya que genera una estructura cíclica que se ajusta en un espacio constante. –

Cuestiones relacionadas