Scala,无限重复有限列表

发布于 2024-08-18 14:42:36 字数 257 浏览 10 评论 0原文

我想在 scala 中使用 Stream 类来无限重复给定的列表。

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

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

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

如何制作一个简单地重复给定列表的流?

I want to use Stream class in scala to repeat a given list infinitely.

For example the list (1,2,3,4,5) I want to create a stream that gives me (1,2,3,4,5,1,2,3,4,5,1,2,3....)

So that I can wrap the take operation. I know this can be implemented in other ways, but I wanna do it this way for some reason, just humor me :)

So the idea is that with this infinite cycle created from some list, I can use take operation, and when it reaches the end of the list it cycles.

How do I make a stream which simply repeats a given list?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

活泼老夫 2024-08-25 14:42:37

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

scala> def xs: Stream[Int] = List(1, 2, 3).toStream #::: xs
xs: Stream[Int]

scala> xs.take(10).toList
res1: List[Int] = List(1, 2, 3, 1, 2, 3, 1, 2, 3, 1)

An alternative method is concatenating the .toStream of the input with itself recursively. That is,

scala> def xs: Stream[Int] = List(1, 2, 3).toStream #::: xs
xs: Stream[Int]

scala> xs.take(10).toList
res1: List[Int] = List(1, 2, 3, 1, 2, 3, 1, 2, 3, 1)
层林尽染 2024-08-25 14:42:37

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)

There is a simple way with 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)
站稳脚跟 2024-08-25 14:42:37

这是一个不假设 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)
}

对于任何 Seq (包括 List 甚至 >Stream),并且只施加恒定的时间开销来填充每个元素。此外,它甚至适用于无限序列。因此,您可以在无限的 Stream 上调用 rep,生成的 Stream 将相当于输入。

Here's an implementation which doesn't assume that length is efficient:

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)
}

This should run in constant time for any Seq (including List or even Stream) and only imposes a constant time overhead to populate each element. Also, it works even for infinite sequences. So, you can call rep on an infinite Stream and the resulting Stream will be equivalent to the input.

雨后彩虹 2024-08-25 14:42:37

公然窃取了优秀的 Scala by Example 书第 12 章,以及进行一些修改:

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)

这适用于所有 Seq 类型(当然,除非它们不能多次读取)。如果 .length 调用很慢,可能效率不高。在 Scala 2.7.7 中测试。

Stolen blatently from the excellent Scala by Example book, chapter 12, and with a few modifications:

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)

This works for all Seq types (unless they can't be read from multiple times, of course). Might not be efficient if the .length call is slow. Tested in Scala 2.7.7.

扛起拖把扫天下 2024-08-25 14:42:36

与@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)

或者,使用 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)

Very similar to @Eastsun's, but a bit more intention revealing. Tested in 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)

Alternatively, with 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)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文