我认为这是处理队列最常见的情况。我将读取队列的前面,对元素执行操作(这可能会导致更多元素添加到队列中),然后循环直到队列为空。
foreach
,但是没有,显然一个队列(甚至是一个可变的队列)是严格的,并且当迭代开始时,foreach遍历队列中的所有元素。while
循环的语法。你认为它会像
while (!q.isEmpty) {
var (e, q) = q.dequeue
... }
除非我重新宣布q
,否则会有效。这确实有效:
while (!q.isEmpty) {
var (e, q1) = q.dequeue
q = q1
... }
但男人,看起来错误 ......
答案 0 :(得分: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)
您从初始队列q0
开始,然后在qi
步骤中,您将某些内容出列并在需要时生成一个新队列,并将其返回到下一步。
你剩下的就是停止条件(非空),然后由于这只是定义一个过程,而不是实际动作,你必须运行它(例如,使用no-op foreach)。
答案 1 :(得分:13)
虽然Rex Kerr' answer很好,但迭代器是可变的。这是一个真正不可改变的解决方案,非常密切地模仿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)
答案 2 :(得分:5)
在Queue
循环中处理while
,无需重复var
/ val
,如下所示:
var q = Queue("foo", "bar", "baz")
while (q.nonEmpty) {
val e = q.head
q = q.tail
// Do something with `e` here
}
(我知道这个答案已经晚了7年,但我认为它仍然是一个有价值的选择。)