PHP学习笔记17:迭代器和生成器
2021/12/10 22:23:57
本文主要是介绍PHP学习笔记17:迭代器和生成器,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
PHP学习笔记17:迭代器和生成器
图源:php.net
迭代器相关概念广泛存在于各种编程语言和设计模式中,这里推荐两篇我的相关文章:
- Python学习笔记31:迭代技术
- 设计模式 with Python 9:迭代器模式
迭代器
php中,可以通过实现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 { } }
这些方法的作用是:
current
,返回游标对应的当前元素。next
,移动游标到下一个元素。rewind
,重置游标到开始位置。key
,返回游标位置。valid
,游标当前的位置是否有效(用于判断是否结束遍历)。
php的迭代器接口比Python中的更复杂,但好处是包含
rewind
方法,可以重置迭代器以重复迭代。
下面用一个可以将字符串内单词分词的程序作为示例:
<?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预设了一些常用的迭代器,具体请参考官方手册迭代器。
生成器
生成器可以看做是一种特殊的迭代器,可以使用生成器函数来便捷地创建一个生成器:
<?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
生成器的优点在于,相比较迭代器,它的实现代码更少,且还可以用yield from
语句将调用委托给另一个生成器,实现类似的生成器多级套用的方式。这点在Python的async
包实现并发时相当常见。
这里展示sentence
套用一个将字符串分解为字母遍历的生成器:
<?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
通过使用生成器,我们可以避免程序中因为遍历大型数组导致的内存占用过多的情况:
<?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
相比较内置的range
函数,这里的xrange
函数可以用于生成超大长度的序列,且只会占用很小的内存。
需要注意的是,生成器函数本身返回的是生成器,其实质上充当了生成器工厂方法的作用。yield
产出的数据只不过是生成器遍历时每次返回的迭代结果,而不是生成器函数的返回值。这点新手很容易搞混淆。
生成器是内置类型Generator
的实例,所以为了明确起见,可以将生成器函数的返回值标注为Generator
类型。
因为在学习Python的过程中详细总结了生成器的相关内容,所以这里只简单介绍了php中生成器和迭代器的用法,更多生成器的内容可以阅读Python学习笔记16:生成器。
谢谢阅读。
往期内容
- PHP学习笔记16:错误处理
- PHP学习笔记15:枚举
- PHP学习笔记14:命名空间
- PHP学习笔记13:类和对象 V
- PHP学习笔记12:类和对象IV
- PHP学习笔记11:类和对象 III
- PHP学习笔记10:类和对象 II
- PHP学习笔记9:类和对象 I
- PHP学习笔记8:函数
- PHP学习笔记7:控制流
- PHP学习笔记6:表达式和运算符
- PHP学习笔记5:常量
- PHP学习笔记4:变量
- PHP学习笔记3:其它类型和类型声明
- PHP学习笔记2:数组
- PHP学习笔记1:基础
这篇关于PHP学习笔记17:迭代器和生成器的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-11-23怎么实现安卓+php 热更新方案?-icode9专业技术文章分享
- 2024-11-22PHP 中怎么实现判断多个值是否为空、null 或者为 false?-icode9专业技术文章分享
- 2024-11-11开源 PHP 商城项目 CRMEB 二次开发和部署教程
- 2024-11-09怎么使用php在kaufland平台刊登商品?-icode9专业技术文章分享
- 2024-11-05PHP的抽象类和接口是什么,有什么区别-icode9专业技术文章分享
- 2024-11-01开源 PHP 商城项目 CRMEB 安装和使用教程
- 2024-11-01用php和mysql写无限分类,有哪几种方法-icode9专业技术文章分享
- 2024-10-31php数据分表导出时部分数据无法导出什么原因-icode9专业技术文章分享
- 2024-10-30有经验的 PHP 开发者学习一门新的编程语言,有哪些推荐的有前景的语言-icode9专业技术文章分享
- 2024-10-21php 检测图片是否篡改过-icode9专业技术文章分享