Итерация по кругу - PullRequest
       21

Итерация по кругу

13 голосов
/ 15 июля 2010

Мне нужно перебрать список, но круговым способом.Мне тоже нужно добавить новые элементы в список и перебрать все элементы (старые и новостные элементы). Как мне это сделать?Есть ли какая-то структура данных для них?

Ответы [ 4 ]

19 голосов
/ 15 июля 2010

Один из вариантов - использовать класс Stream для создания ленивой, круговой бесконечной последовательности:

scala> val values = List(1, 2, 3)
values: List[Int] = List(1, 2, 3)

scala> Stream.continually(values.toStream).flatten.take(9).toList
res2: List[Int] = List(1, 2, 3, 1, 2, 3, 1, 2, 3)

или так:

val values = List(1, 2, 3)

def circularStream(values: List[Int],
                   remaining: List[Int] = List()): Stream[Int] = {

  if (remaining.isEmpty)
    circularStream(values,values)
  else
    Stream.cons(remaining.head, circularStream(values, remaining.drop(1)))
}

circularStream(values).take(9).toList //Same result as example #1
10 голосов
/ 16 июля 2010
def forever:Stream[Int] = Stream(1,2,3) append forever
7 голосов
/ 15 июля 2010

Подобные вещи действительно заслуживают того, чтобы быть в стандартной потоковой библиотеке, но, похоже, их нет.Ответ dbryne с потоком работает хорошо, или, если вы предпочитаете его в форме для понимания

val listToRepeat:List[Foo]
val forever:Stream[Foo] = for(x<-Stream.continually(1); y<-listToRepeat) yield y

Первый генератор потока позволяет работать вечно, даже если вы игнорируете значение.Второй генератор неявно сплющивается в нужный вам бесконечный поток.

6 голосов
/ 16 июля 2010

Я думаю, может быть, это то, что вы хотите; возможность добавлять новые элементы в ваш список, даже когда вы выполняете его. Код некрасив, но, похоже, работает.

import scala.collection.mutable.Queue

class Circular[A](list: Seq[A]) extends Iterator[A]{

  val elements = new Queue[A] ++= list
  var pos = 0

  def next = {
    if (pos == elements.length) 
      pos = 0
    val value = elements(pos)
    pos = pos + 1
    value
  }

  def hasNext = !elements.isEmpty
  def add(a: A): Unit = { elements += a }
  override def toString = elements.toString

}

Вы можете использовать это так:

scala> var circ = new Circular(List(1,2))
res26: Circular[Int] = Queue(1,2)
scala> circ.next
res27: Int = 1
scala> circ.next
res28: Int = 2
scala> circ.next
res29: Int = 1
scala> circ.add(5)
scala> circ.next
res30: Int = 2
scala> circ.next
res31: Int = 5
scala> circ
res32: Circular[Int] = Queue(1,2,5)
...