Dav*_*ues 37 php arrays iterator generator
今天PHP团队发布了PHP 5.5.0版本,其中包括对生成器的支持.阅读文档,我注意到它完全可以用数组做.
PHP团队生成器示例:
// Only PHP 5.5
function gen_one_to_three() {
for ($i = 1; $i <= 3; $i++) {
// Note that $i is preserved between yields.
yield $i;
}
}
$generator = gen_one_to_three();
foreach ($generator as $value) {
echo "$value\n";
}
Run Code Online (Sandbox Code Playgroud)
结果:
1
2
3
Run Code Online (Sandbox Code Playgroud)
但我可以使用数组做同样的事情.我仍然可以保持与早期版本的PHP兼容.
看看:
// Compatible with 4.4.9!
function gen_one_to_three() {
$results = array();
for ($i = 1; $i <= 3; $i++) {
$results[] = $i;
}
return $results;
}
$generator = gen_one_to_three();
foreach ($generator as $value) {
echo "$value\n";
}
Run Code Online (Sandbox Code Playgroud)
所以问题是:这个新功能的存在目的是什么?我必须在不使用新功能的情况下播放所有文档示例,将其替换为数组.
任何人都可以给出一个很好的解释,也许是旧版本不一定不可能的例子,但使用生成器可以帮助开发吗?
irc*_*ell 59
不同之处在于效率.例如,PHP以外的许多语言包括两个range
函数,range()
和xrange()
.这是生成器的一个很好的例子,以及为什么要使用它们.让我们建立自己的:
function range($start, $end) {
$array = array();
for ($i = $start; $i <= $end; $i++) {
$array[] = $i;
}
return $array;
}
Run Code Online (Sandbox Code Playgroud)
现在,这真的很直接.但是,对于大范围,它需要大量的内存.如果我们尝试用$start = 0
和运行它$end = 100000000
,我们可能会耗尽内存!
但如果我们使用发电机:
function xrange($start, $end) {
for ($i = $start; $i <= $end; $i++) {
yield $i;
}
}
Run Code Online (Sandbox Code Playgroud)
现在我们使用常量内存,但仍然有一个"数组"(比如结构),我们可以在同一个空间中迭代(并与其他迭代器一起使用).
它不会取代数组,但它确实提供了避免需要内存的有效方法......
但它也可以节省物品的生成.由于每个结果都是根据需要生成的,因此您可以延迟执行(获取或计算)每个元素,直到您需要它为止.因此,例如,如果您需要从数据库中获取项目并对每行执行一些复杂的处理,则可以使用生成器延迟该项,直到您实际需要该行为止:
function fetchFromDb($result) {
while ($row = $result->fetchArray()) {
$record = doSomeComplexProcessing($row);
yield $record;
}
}
Run Code Online (Sandbox Code Playgroud)
因此,如果您只需要前3个结果,则只需处理前三个记录.
Mar*_*ker 11
在开始循环之前,数组必须包含您循环的每个值; 生成器根据请求"动态"创建每个值,因此内存更少;
数组使用它包含的值,并且必须预先填充这些值; 生成器可以根据直接使用的特殊标准创建值...例如,斐波纳西序列,或来自非AZ字母表的字母(通过UTF-8数值计算)有效地允许alphaRange('א','ת' );
编辑
function fibonacci($count) {
$prev = 0;
$current = 1;
for ($i = 0; $i < $count; ++$i) {
yield $prev;
$next = $prev + $current;
$prev = $current;
$current = $next;
}
}
foreach (fibonacci(48) as $i => $value) {
echo $i , ' -> ' , $value, PHP_EOL;
}
Run Code Online (Sandbox Code Playgroud)
编辑
只是为了好玩,这是一个将希伯来字母作为UTF-8字符返回的生成器
function hebrewAlphabet() {
$utf8firstCharacter = 1488;
$utf8lastCharacter = 1514;
for ($character = $utf8firstCharacter; $character <= $utf8lastCharacter; ++$character) {
yield html_entity_decode('&#'.$character.';', ENT_NOQUOTES, 'UTF-8');
};
}
foreach(hebrewAlphabet() as $character) {
echo $character, ' ';
}
Run Code Online (Sandbox Code Playgroud)