phpiteratorspl

SplPriorityQueue::next() is removing the item


I would like to know how could I iterate a SplHeap or SplPriorityQueue more than once.

next() method removes the last item, so the second foreach (or for) is not getting any result.

Example:

<?php
class Teste extends SplPriorityQueue {}

$teste = new Teste();
$teste->insert( 'A', 1 );
$teste->insert( 'B', 3 );
$teste->insert( 'D', 5 );
$teste->insert( 'C', 2 );
$teste->insert( 'A', 4 );

echo '<pre>';

var_dump( $teste->count() );

echo '<br>';

foreach( $teste as $t )
    var_dump( $t );

echo '<br>';

var_dump( $teste->count() );

Returns:

int(5)

string(1) "D"
string(1) "A"
string(1) "B"
string(1) "C"
string(1) "A"

int(0) <--- I need this to still be 5

I need to insert items based on a compare() method, like this: http://php.net/manual/en/splheap.compare.php

Thanks!


Solution

  • I would like to know how could I iterate a SplHeap or SplPriorityQueue more than once.

    The short answer is, you don't iterate more than once for an individual instance of the class.

    The slightly longer answer is to instead use multiple identical instances when iterating. This can be easily achieved by iterating over a clone of the heap/pqueue.

    Quicky example

    <?php
    
    $queue = new SplPriorityQueue();
    $queue ->insert('A', 30);
    $queue ->insert('C', 10);
    $queue ->insert('B', 20);
    
    var_dump(count($queue));
    foreach (clone $queue as $item) {
        var_dump($item);
    }
    var_dump(count($queue));
    foreach (clone $queue as $item) {
        var_dump($item);
    }
    var_dump(count($queue));
    

    The above outputs:

    int(3)
    string(1) "A"
    string(1) "B"
    string(1) "C"
    int(3)
    string(1) "A"
    string(1) "B"
    string(1) "C"
    int(3)