gpt4 book ai didi

php - PHP 中的递归生成器

转载 作者:IT王子 更新时间:2023-10-29 01:14:02 25 4
gpt4 key购买 nike

简介

自从 PHP 5.5 版本以来,generators .我不会重复官方手册页,但它们对于迭代器的简短定义非常有用。最知名的样本是:

function xrange($from, $till, $step)
{
if ($from>$till || $step<=0)
{
throw new InvalidArgumentException('Invalid range initializers');
}

for ($i = $from; $i < $till; $i += $step)
{
yield $i;
}
}

//...

foreach (xrange(2, 13, 3) as $i)
{
echo($i.PHP_EOL); // 2,5,8,11
}

而生成器实际上不是一个函数,而是一个具体类的实例:

get_class(xrange(1, 10, 1)); // Generator


问题

完成了 RTM 的内容,现在继续我的问题。假设我们要创建 Fibonacci numbers 的生成器.通常,要获得这些,我们可以使用简单的函数:

function fibonacci($n)
{
if(!is_int($n) || $n<0)
{
throw new InvalidArgumentException('Invalid sequence limit');
}
return $n < 2 ? $n : fibonacci($n-1) + fibonacci($n-2);
}

var_dump(fibonacci(6)); // 8

让我们把它转换成某种东西,它包含 sequence 而不仅仅是它的最后一个成员:

function fibonacci($n)
{
if (!is_int($n) || $n<0)
{
throw new InvalidArgumentException('Invalid sequence limit');
}
if ($n<2)
{
return range(0, $n);
}
$n1 = fibonacci($n-1);
$n2 = fibonacci($n-2);
return array_merge($n1, [array_pop($n1)+array_pop($n2)]);
}

//...

foreach (fibonacci(6) as $i)
{
echo($i.PHP_EOL); // 0,1,1,2,3,5,8
}

我们现在有一个返回完整序列数组的函数


问题

最后,问题部分:如何转换我最新的 fibonacci 函数,使其产生我的值,而不是将它们保存在数组中?我的 $n 可能很大,所以我想利用生成器的好处,例如 xrange 示例。伪代码将是:

function fibonacci($n)
{
if (!is_int($n) || $n<0)
{
throw new InvalidArgumentException('Invalid sequence limit');
}

if ($n<2)
{
yield $n;
}

yield fibonacci($n-2) + fibonacci($n-1);
}

但这显然是废话,因为我们不能这样处理它,因为递归将导致类 Generator 的对象而不是 int 值。

奖励:获取斐波那契数列只是更一般问题的一个示例:在常见情况下如何使用具有递归的生成器?当然,我可以使用标准 Iterator为此或重写我的函数以避免递归。但我想用生成器来实现。这可能吗?这值得努力使用这种方式吗?

最佳答案

因此,我在尝试创建递归生成器函数时遇到的问题是,一旦您超过第一个深度级别,每个后续的 yield 都会屈服于其父调用而不是迭代实现(循环)。

从 php 7 开始,添加了一项新功能,允许您yield from 后续生成器函数。这是新的 Generator Delegation 功能:https://wiki.php.net/rfc/generator-delegation

这允许我们从后续的递归调用中产生 yield ,这意味着我们现在可以使用生成器高效地编写递归函数。

$items = ['what', 'this', 'is', ['is', 'a', ['nested', 'array', ['with', 'a', 'bunch',  ['of', ['values']]]]]];

function processItems($items)
{
foreach ($items as $value)
{
if (is_array($value))
{
yield from processItems($value);
continue;
}
yield $value;
}
}

foreach (processItems($items) as $item)
{
echo $item . "\n";
}

这给出了以下输出..

what
this
is
is
a
nested
array
with
a
bunch
of
values

关于php - PHP 中的递归生成器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19835499/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com