我“应该”如何使用 scala.collection.immutable.Queue?

发布于 2024-10-09 01:12:56 字数 470 浏览 2 评论 0原文

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

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

您可能会认为这会起作用

while (!q.isEmpty) {
   var (e, q) = q.dequeue
   ... }

,只是我重新声明了 q。这确实有效:

while (!q.isEmpty) {
   var (e, q1) = q.dequeue
   q = q1
   ... }

但是伙计,它看起来错误吗?

I have what I would think is the most common case for processing a queue. I will read off the front of the queue, act on the element (which may cause more elements to be added to the queue), and then loop until the queue is empty.

  1. My first instinct was foreach, but no, apparently a queue (even a mutable one) is strict and the foreach loops over all the elements that are in the queue when the iteration starts.
  2. I cannot figure out the syntax for a while loop.

You'd think that it would be something like

while (!q.isEmpty) {
   var (e, q) = q.dequeue
   ... }

would work, except that I'm redeclaring q. This does work:

while (!q.isEmpty) {
   var (e, q1) = q.dequeue
   q = q1
   ... }

but man, does it look wrong ...

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

自演自醉 2024-10-16 01:12:56

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

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 步中,将某些内容出列并生成一个新队列,如果需要,将其返回以进行下一步。

您剩下的就是停止条件(不为空),然后由于这只是定义了一个进程,而不是实际操作,因此您必须运行它(例如,使用无操作 foreach)。

Here's one way to avoid any vars at all:

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)

You start with the initial queue, q0, and then on the qith step, you dequeue something and produce a new queue if need be, returning that for the next step.

All you have left is the stopping condition (not empty), and then since this just defines a process, not the actual action, you have to run it (using a no-op foreach, for example).

-残月青衣踏尘吟 2024-10-16 01:12:56

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)

While Rex Kerr's answer is good, iterators are mutable. Here's a truly immutable solution, modeled very closely on the code in Rex Kerr's own answer.

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)
趴在窗边数星星i 2024-10-16 01:12:56

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

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

我是意识到这个答案晚了 7 年,但我认为它仍然是一个有价值的选择。)

Processing a Queue in a while loop can be done without a duplicate var/val as follows:

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

(I am aware that this answer is 7 years late, but I thought it a valuable alternative nonetheless.)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文