Бесконечный цикл с SplQueue

Мне нужна очередь, в которую я добавляю объекты во время работы с очередью (первым пришел - первым вышел). Кроме того, я отслеживаю отсутствие дублирующих объектов в хэш-карте.

<?php

$test = new \SplQueue();
$done = array();

// Put 'test a' in queue
$test->enqueue('test a');

// While we have objects in the queue...
while ($test->valid()) {
    // Echo the current object
    $current = $test->current();
    echo $current, PHP_EOL;

    // Remove the current object and add it to "done"
    $test->dequeue();
    $done[$current] = 1;

    // Add more to queue
    $new = array('test a', 'test b', 'test c');
    foreach ($new as $newObject) {
        if (! isset($done[$newObject])) {
            $test->enqueue($newObject);
        }
    }
}

В коде PHP я не получаю никакого результата с этим. Что случилось?

Обновление: Через некоторое время я получаю вывод:

test a 
Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 32 bytes) in /code/NIPg42 on line 25
PHP Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 32 bytes) in /code/NIPg42 on line 25

Я делаю dequeue и проверяю уже готовые объекты, почему это бесконечный цикл?

Строка 25 $test->enqueue($newObject);

1 ответ

Решение

Для меня проще (и более естественно, тоже) работать с SplQueue, используя только два основных метода: enqueue поместить элемент в конец очереди и dequeue чтобы извлечь элемент, который вам нужно обработать с начала очереди. Это значит избавиться от current, используя результат dequeue вместо:

$current = $test->dequeue();
$done[$current] = 1;
var_dump($current); // or any other processing

Поскольку попытка удалить пустой список приводит к ошибке, сначала вам нужно ее проверить. Таким образом, ваш код становится похожим на это:

$test = new \SplQueue();
$done = array();

// Put 'test a' in queue
$test->enqueue('test a');

// While we have objects in the queue...
while (!$test->isEmpty()) {
    $item = $test->dequeue();
    $done[$item] = 1;
    var_dump($item); 

    // Add more to queue
    $new = array('test a', 'test b', 'test c');
    foreach ($new as $newObject) {
        if (! isset($done[$newObject])) {
            $test->enqueue($newObject);

// without this line, `test c` will be enqueued twice.
            $done[$newObject] = 1; 
        }
    }
}

Демо Как видите, здесь есть еще одно изменение: установка хеша перед выполнением enqueue, Если вы действительно хотите создать HashQueue (в некотором роде), я бы предложил создать свой собственный класс (расширение или использование SplQueue); ключ будет сопровождать каждого enqueue работа с соответствующей проверкой / дополнением к хешу.

Другие вопросы по тегам