【问题标题】:Is there a Round Robin/Circular Queue available in Scala CollectionsScala Collections 中是否有可用的循环/循环队列
【发布时间】:2013-11-15 07:46:07
【问题描述】:

Scala 集合中是否提供循环队列?

我需要反复迭代一个自循环的列表

val x = new CircularList(1,2,3,4)
x.next (returns 1)
x.next (returns 2)
x.next (returns 3)
x.next (returns 4)
x.next (returns 1)
x.next (returns 2)
x.next (returns 3)

...等等

【问题讨论】:

    标签: scala scala-collections scala-2.10


    【解决方案1】:

    版本更侧重于在每次执行时获取新元素。

    val getNext: () => Int = {
      def b: Stream[Int] = List(1, 2, 3, 4).toStream #::: b
      var cyclicIterator: Stream[Int] = b
      () => {
        val tail = cyclicIterator.tail
        val result = tail.head
        cyclicIterator = tail
        result 
      }
    } // could be written more sexy?
    

    在您的问题中,您可以像这样使用它:

    for(i <- 1 to 10) yield getNext()
    

    【讨论】:

      【解决方案2】:

      您可以使用Stream 非常轻松地创建一个循环列表。

      scala> val l = List(1, 2, 3, 4).toStream
      l: scala.collection.immutable.Stream[Int] = Stream(1, ?)
      
      scala> def b: Stream[Int] = l #::: b
      b: Stream[Int]
      
      scala> b.take(20).toList
      res2: List[Int] = List(1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4)
      

      编辑:您要确保事先定义重复部分,一次且仅一次,以避免炸毁堆(Stream 中的结构共享)。如:

      def circular[A](a: Seq[A]): Stream[A] = {
        val repeat = a.toStream
        def b: Stream[A] = repeat #::: b
        b
      }
      

      【讨论】:

      • 不幸的是,我正在使用 scala 2.9.2 :) 并且迭代器是 2.10 的一部分 .. 是否有向后兼容的版本?
      • 嗯,我刚刚测试过,两个版本(StreamIterator)在 2.9.2 中都可以正常工作。
      • 我想说@TravisBrown 提供的解决方案更适合这种情况,因为Iterator 提供了next 方法。
      【解决方案3】:

      拥有一个外部可变索引很难看,但它确实可以满足要求:

      scala> var i = 0
      scala> val ic4 = Iterator.continually { val next = IndexedSeq(1, 2, 3, 4)(i % 4); i += 1; next }
      i: Int = 0
      ic4: Iterator[Int] = non-empty iterator
      
      scala> ic4 take 10 foreach { i => printf("ic4.next=%d%n", i) }
      ic4.next=1
      ic4.next=2
      ic4.next=3
      ic4.next=4
      ic4.next=1
      ic4.next=2
      ic4.next=3
      ic4.next=4
      ic4.next=1
      ic4.next=2
      

      至少它说明了Iterator.continually。还有Stream.continually,签名相同。

      【讨论】:

        【解决方案4】:

        使用continuallyflatten 很容易推出自己的产品:

        scala> val circular = Iterator.continually(List(1, 2, 3, 4)).flatten
        circular: Iterator[Int] = non-empty iterator
        
        scala> circular.take(17).mkString(" ")
        res0: String = 4 1 2 3 4 1 2 3 4 1 2 3 4 1 2 3 4
        

        Stream 上还有一个 continually 方法 — 如果要生成大量元素,请注意不要持有对流头部的引用。

        【讨论】:

        • 这是一个更好的答案,因为与 Stream 相比,您不会占用资源
        • @Jatin 好点,我编辑了我的答案。我同意,这个版本不太容易出错。
        • 不幸的是,我正在使用 scala 2.9.2 :) 并且迭代器是 2.10 的一部分 .. 是否有向后兼容的版本?
        • @user2780187: Iterator 已经存在很长时间了——我刚刚在 2.9.2 中测试了这段代码,它按预期工作。
        • 请注意Stream.continually 不会形成循环结构(常量内存);它会不断重复(可能无限使用内存)。
        猜你喜欢
        • 2012-08-05
        • 1970-01-01
        • 1970-01-01
        • 2012-07-06
        • 1970-01-01
        • 2014-01-05
        • 1970-01-01
        • 1970-01-01
        • 2011-11-13
        相关资源
        最近更新 更多