Подтвердить что ты не робот

Scala, бесконечно повторять конечный список

Я хочу использовать класс Stream в scala для бесконечного повторения данного списка.

Например, список (1,2,3,4,5) Я хочу создать поток, который дает мне (1,2,3,4,5,1,2,3,4,5,1, 2,3....)

Чтобы я мог завершить операцию take. Я знаю, что это может быть реализовано другими способами, но я хочу сделать это по какой-то причине, просто юмористически меня:)

Итак, идея состоит в том, что с этим бесконечным циклом, созданным из некоторого списка, я могу использовать операцию принятия, и когда он достигнет конца списка, он циклически выполняет.

Как создать поток, который просто повторяет данный список?

4b9b3361

Ответ 1

Очень похоже на @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)

Ответ 2

Альтернативный метод заключается в конкатенации .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)

Ответ 3

Существует простой способ спрятать Stream # в 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)

Ответ 4

Здесь реализована реализация, которая не предполагает, что 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) и только накладывает постоянную временную нагрузку для заполнения каждого элемента. Кроме того, он работает даже для бесконечных последовательностей. Таким образом, вы можете вызвать rep в бесконечном Stream, и полученный Stream будет эквивалентен вводу.

Ответ 5

Вкратце украдены из отличной Scala по примеру книги, глава 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 (если они не могут быть прочитаны из нескольких раз, конечно). Не может быть эффективным, если длительность вызова медленная. Протестировано в Scala 2.7.7.