Как я * должен * использовать scala.collection.immutable.Queue? - PullRequest
22 голосов
/ 27 декабря 2010

У меня есть то, что я считаю наиболее распространенным случаем для обработки очереди. Я прочитаю начало очереди, воздействую на элемент (что может привести к добавлению большего количества элементов в очередь), а затем зациклюсь, пока очередь не станет пустой.

  1. Мой первый инстинкт был foreach, но нет, очевидно, очередь (даже изменяемая) строгая, и foreach зацикливается на всех элементах в очереди, когда итерация начинается.
  2. Я не могу понять синтаксис для цикла while.

Вы могли бы подумать, что это будет что-то вроде

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

будет работать, за исключением того, что я изменяю порядок q. Это работает:

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

но человек, это выглядит неправильно ...

Ответы [ 3 ]

17 голосов
/ 28 декабря 2010

Вот один из способов вообще избежать любых переменных:

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 без операции).

13 голосов
/ 28 декабря 2010

Хотя Рекс Керр ответ хорошо, итераторы изменчивы. Вот действительно неизменное решение, очень близко смоделированное кодом из собственного ответа Рекса Керра.

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)
5 голосов
/ 12 июля 2017

Обработка 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 лет, но я все же подумал, что это ценная альтернатива.)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...