我怎么样*要使用scala.collection.immutable.Queue?

Mal*_*lio 22 scala

我有我认为处理队列最常见的情况.我将读取队列的前面,对元素执行操作(这可能会导致更多元素添加到队列中),然后循环直到队列为空.

  1. 我的第一直觉是foreach,但是没有,显然一个队列(甚至是一个可变的队列)是严格的,并且当迭代开始时,foreach循环遍历队列中的所有元素.
  2. 我无法弄清楚while循环的语法.

你会认为它会是这样的

while (!q.isEmpty) {
   var (e, q) = q.dequeue
   ... }
Run Code Online (Sandbox Code Playgroud)

会工作,除了我重新宣布q.这确实有效:

while (!q.isEmpty) {
   var (e, q1) = q.dequeue
   q = q1
   ... }
Run Code Online (Sandbox Code Playgroud)

但男人,看起来不对 ......

Rex*_*err 17

这是避免任何变量的一种方法:

val q0 = collection.immutable.Queue("1","Two","iii")
Iterator.iterate(q0) { qi =>
  val (e,q) = qi.dequeue
  println("I just dequeued "+e)  // Your side-effecting operations go here
  if (e.length!=2) q.enqueue("..")  // Your changes to the queue go here
  else q
}.takeWhile(! _.isEmpty).foreach(identity)
Run Code Online (Sandbox Code Playgroud)

您从初始队列开始q0,然后在qi第一步,您将某些内容出列并在需要时生成一个新队列,并将其返回到下一步.

你剩下的就是停止条件(非空),然后由于这只是定义一个过程,而不是实际动作,你必须运行它(例如,使用no-op foreach).


Dan*_*ral 13

虽然Rex Kerr答案很好,但迭代器是可变的.这是一个真正不可改变的解决方案,非常密切地模拟Rex Kerr自己的答案中的代码.

val q0 = collection.immutable.Queue("1","Two","iii")
@annotation.tailrec def processQueue(queue: collection.immutable.Queue[String]): Unit = if (queue.nonEmpty) {
    val (element, rest) = queue.dequeue
    println("I just dequeued "+element)
    if (element.length != 2) processQueue(rest.enqueue(".."))
    else processQueue(rest)
}
processQueue(q0)
Run Code Online (Sandbox Code Playgroud)

  • 如果我从这个问题和各种反应中得不到任何其他东西,那就是"这个论点绝对是僵尸"的表达,我打算在下次机会时使用它,之后经常使用. (6认同)
  • @Rex Kerr 每个代码在内部都是可变的,因为我们使用的所有真正的处理器都不能在没有可变性的情况下做一件事,所以这个论点绝对是胡说八道。这是编译器端的优化,与程序员无关。 (2认同)
  • 对于那些像我一样,想知道_bollocks_来自何处及其含义的人:http://en.wikipedia.org/wiki/Bollocks.非常有趣,它已经意味着_nonsense_. (2认同)

Nth*_*tal 5

Queuewhile循环中处理a 可以在没有重复var/的情况下完成val,如下所示:

var q = Queue("foo", "bar", "baz")
while (q.nonEmpty) {
  val e = q.head
  q = q.tail
  // Do something with `e` here
}
Run Code Online (Sandbox Code Playgroud)

(我知道这个答案已经晚了7年,但我认为它仍然是一个有价值的选择.)