2015-02-01 1 views
3

Мне нужна очередь, где я добавляю объекты во время работы очереди (сначала в первом порядке). Кроме того, я отслеживаю отсутствие дубликатов объектов в хэшмапе.Бесконечная петля с 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 я не получаю никакого результата. Что не так?

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

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);

+0

Вам нужно будет указать правильный начальный узел (с '$ test-> rewind()', как в [этой демонстрации] (https://eval.in/274359)). Должен сказать, что я не совсем уверен, почему вы хотите использовать SplQueue таким образом. – raina77ow

+0

Более естественно работать с Очереди без использования 'current' вообще; в противном случае вам нужно будет убедиться, что его текущий узел действительно является текущим. Я опишу возможный подход в своем ответе, если вы хотите, чтобы я это сделал. – raina77ow

+0

Что делает метод 'valid'? Для меня это имеет другое поведение, чем 'isEmpty'. –

ответ

2

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

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

В попытке DEQUEUE пустой список вызывает ошибку, вы должны проверить для него первым. Таким образом, ваш код будет выглядеть примерно так:

$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; 
     } 
    } 
} 

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

+0

Так что я использовал SplQueue неправильно, ваш путь действительно более естественный, спасибо! – DanFromGermany

+0

Я уже расширяю SplQueue для отслеживания обработанных объектов; Очень хорошая идея. Не ставил это, чтобы держать этот код в простейшем. – DanFromGermany