Traversal with PHP iterator

Keywords: Programming PHP

We know that PHP traversal is actually an iterator operation. From PHP5, there is an iterator interface, as follows

/**
 * Interface for external iterators or objects that can be iterated
 * themselves internally.
 * @link https://php.net/manual/en/class.iterator.php
 */
interface Iterator extends Traversable {

    /**
     * Return the current element Returns the current element
     */
    public function current();

    /**
     * Move forward to next element Point the pointer to the next element
     */
    public function next();

    /**
     * Return the key of the current element Returns the key of the current element
     */
    public function key();

    /**
     * Checks if current position is valid Check if the current location is legal
     */
    public function valid();

    /**
     * Rewind the Iterator to the first element Reset iterator to first element
     */
    public function rewind();
}

Let's try to use this iterator to traverse the array.

This iterator is an interface, so we need to implement it with a class, as follows

1 iterator

class TestIterator implements Iterator {
    public $object;//object
    public $count;//Number of data elements
    public $current;//Current pointer

    public function __construct($object)
    {
        if (is_object($object)) {
            $this->object = $object;
            $this->count = count($this->object->data);
        }
    }
    
    public function current() {
        return $this->object->data[$this->current];
    }


    public function next() {
        $this->current++;
    }


    public function key() {
        return $this->current;
    }


    public function valid() {
        return $this->current < $this->count;
    }
    
    public function rewind() {
        $this->current = 0;
    }
}

2 iteration generator

//Iteration generator
Interface IteratorGenerator {
    //Get iterator
    function getIterator();
}

class TestIteratorGenerator implements IteratorGenerator {
    public $data = array();

    public function __construct($in)
    {
        $this->data = $in;
    }

    //Get iterator
    public function getIterator() {
        return new TestIterator($this);
    }
}

Then, we can get an iteration object through the iteration generator, as follows

$arr = ['aa', 'bb', 'cc'];
//Iteration generator
$generator = new TestIteratorGenerator($arr);
//Iterative object
$obj = $generator->getIterator();

3 implement for() loop

First let's look at the definition of the for() loop

for (expr1; expr2; expr3) {
    statement
}

expr1 is evaluated (and executed) unconditionally once before the loop begins.
expr2 is evaluated before the start of each cycle. If TRUE, the loop continues, executing the nested loop statement. If the value is FALSE, the loop is terminated.
expr3 is evaluated (and executed) after each loop.
Each expression can be empty or include multiple expressions separated by commas. In expr2, all comma separated expressions will be evaluated (there can be more than one), but only the last result will be taken. Empty expr2 means infinite loop down (like C, PHP defaults to TRUE).

Let's do it

for ($obj->rewind(); $obj->valid(); $obj->next()) {
    $key = $obj->key();
    $value = $obj->current();
    echo $key.'=>'.$value."\n";
}

//Result:
0=>aa
1=>bb
2=>cc

4 implement foreach() loop

$obj->rewind();
while ($obj->valid()) {
    $key = $obj->key();
    $value = $obj->current();
    foreach ($arr as $key => $value) {
        echo $key.'=>'.$value."\n";
        $obj->next();
    }
}

//Result:
0=>aa
1=>bb
2=>cc

Posted by wsantos on Tue, 07 Apr 2020 08:36:04 -0700