Scala,无限重复有限列表

Fel*_*lix 31 scala list stream infinite

我想在scala中使用Stream类无限地重复给定列表.

例如列表(1,2,3,4,5)我想创建一个给我的流(1,2,3,4,5,1,2,3,4,5,1,2,3) ....)

这样我就可以包装take操作了.我知道这可以通过其他方式实现,但我想出于某种原因这样做,只是幽默我:)

所以我的想法是,通过从某个列表创建的无限循环,我可以使用take操作,当它到达列表的末尾时,它会循环.

如何创建一个简单重复给定列表的流?

ret*_*nym 37

与@ Eastsun非常相似,但更多的意图揭示.在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)
Run Code Online (Sandbox Code Playgroud)

或者,使用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)
Run Code Online (Sandbox Code Playgroud)

  • 我认为值得注意的是,"Stream.continually(...).flatten"方法导致重复结构具有无限的潜在空间消耗,而不是适合恒定空间的循环结构(如Volcan的答案). (2认同)

Vol*_*ıcı 25

另一种方法是.toStream递归地将输入与其自身连接起来.那是,

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)
Run Code Online (Sandbox Code Playgroud)

  • 我认为这是最好的方法,因为它产生了一个适合恒定空间的循环结构. (2认同)

Eas*_*sun 7

在scala 2.8中使用Stream#flatten有一种简单的方法

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)
Run Code Online (Sandbox Code Playgroud)


Dan*_*wak 5

这是一个不假设length有效的实现:

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)
}
Run Code Online (Sandbox Code Playgroud)

这应该在任何Seq(包括List或甚至Stream)的恒定时间内运行,并且仅对填充每个元素施加恒定的时间开销.此外,它甚至适用于无限序列.因此,您可以调用rep无限Stream,结果Stream将等同于输入.