PHP learning notes 17: iterators and generators
Source: php.net
Iterator related concepts widely exist in various programming languages and design patterns. Here are two related articles I recommend:
iterator
In php, you can implement Iterator interface To implement an iterator:
<?php class MyClass implements Iterator { public function current(): mixed { } public function next(): void { } public function rewind(): void { } public function key(): mixed { } public function valid(): bool { } }
The functions of these methods are:
- Current, returns the current element corresponding to the cursor.
- Next, move the cursor to the next element.
- rewind to reset the cursor to the start position.
- key to return the cursor position.
- Valid, whether the current position of the cursor is valid (used to judge whether to end the traversal).
php's iterator interface is more complex than Python's, but the advantage is that it includes the rewind method, which can reset the iterator to repeat the iteration.
The following is an example of a program that can segment words in a string:
<?php class Sentence implements Iterator { private array $words; private int $index = 0; public function __construct(string $string) { $this->words = str_word_count($string, 1); } public function current(): mixed { return $this->words[$this->index]; } public function rewind(): void { $this->index = 0; } public function next(): void { $this->index++; } public function key(): mixed { return $this->index; } public function valid(): bool { return isset($this->words[$this->index]); } } $sentence = new Sentence("hello world, how are you!"); foreach ($sentence as $word) { echo $word . PHP_EOL; } echo PHP_EOL; // hello // world // how // are // you
php has preset some common iterators. Please refer to the official manual for details iterator .
generator
The generator can be regarded as a special iterator. You can use the generator function to easily create a generator:
<?php function sentence(string $str) { $words = str_word_count($str, 1); foreach ($words as $key => $val) { yield $val; } } foreach (sentence("hello world, how are you!") as $word) { echo $word . PHP_EOL; } // hello // world // how // are // you
The advantage of the generator is that it has less implementation code than the iterator, and it can also delegate the call to another generator with the yield from statement to implement a similar multi-level application of the generator. This is quite common when Python's async package implements concurrency.
Here, sentence uses a generator that decomposes a string into letters for traversal:
<?php function char(string $str): Generator { $len = strlen($str); if ($len == 0) { yield ""; return; } $index = 0; do { yield substr($str, $index, 1); $index++; } while ($index <= $len - 1); } function sentence(string $str): Generator { $words = str_word_count($str, 1); foreach ($words as $key => $val) { yield from char($val); } } foreach (sentence("hello world, how are you!") as $word) { echo $word . " "; } echo PHP_EOL; // h e l l o w o r l d h o w a r e y o u
By using the generator, we can avoid excessive memory consumption caused by traversing large arrays in the program:
<?php function xrange(int $start, int $end, int $step): Generator { if ($step <= 0) { throw new Exception("invlid step param."); } if ($start < $end) { for ($i = $start; $i <= $end; $i += $step) { yield $i; } } else { for ($i = $start; $i >= $end; $i -= $step) { yield $i; } } } function print_generator(Generator $gen) { foreach ($gen as $val) { echo $val . " "; } echo PHP_EOL; } $gen1 = xrange(1, 10, 1); $gen2 = xrange(20, 3, 3); print_generator($gen1); print_generator($gen2); // 1 2 3 4 5 6 7 8 9 10 // 20 17 14 11 8 5
Compared with the built-in range function, the xrange function here can be used to generate super long sequences, and will only occupy a small memory.
It should be noted that the generator function itself returns a generator, which essentially acts as a generator factory method. The data produced by yield is only the iteration result returned each time the generator traverses, not the return value of the generator function. This is easily confused by novices.
The Generator is an instance of the built-in type Generator, so for clarity, you can label the return value of the Generator function as the Generator type.
Because the relevant contents of the generator are summarized in detail in the process of learning Python, here is only a brief introduction to the usage of the generator and iterator in php. You can read more about the generator Python learning note 16: generator.
Thank you for reading.
Previous contents
- PHP learning notes 16: error handling
- PHP learning notes 15: Enumeration
- PHP learning notes 14: namespace
- PHP learning notes 13: classes and objects V
- PHP learning notes 12: classes and objects IV
- PHP learning notes 11: classes and objects III
- PHP learning notes 10: classes and objects II
- PHP learning notes 9: classes and objects I
- PHP learning notes 8: Functions
- PHP learning note 7: control flow
- PHP Learning Notes 6: expressions and operators
- PHP learning notes 5: constants
- PHP learning notes 4: Variables
- PHP learning note 3: other types and type declarations
- PHP learning notes 2: array
- PHP learning notes 1: Basics