当前位置: 首页 > 知识库问答 >
问题:

生成器和阵列之间的区别是什么?

邵飞鸿
2023-03-14

今天,PHP团队发布了PHP5.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";
}

结果:

1
2
3

但是我可以用数组做同样的事情。我仍然可以与早期版本的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";
}

那么问题来了:这个新功能存在的目的是什么?我得发挥所有的例子留档不使用新功能,用数组取代它。

有人能给出一个很好的解释,也许是一个例子,在旧版本中不一定是不可能的,但是使用生成器可以帮助开发吗?

共有3个答案

慕项明
2023-03-14

数组必须包含在开始循环之前循环的每个值;生成器根据请求“动态”创建每个值,因此内存要少得多;

数组与它包含的值一起工作,并且必须预先填充这些值;生成器可以根据直接使用的特殊标准创建值...例如fibonnaci序列,或者来自非A-Z字母表的字母(由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;
}

编辑

只是为了好玩,这里有一个生成器,它将希伯来字母返回为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, ' ';
}
锺英彦
2023-03-14

生成器允许延迟计算复杂语句。这样你就节省了内存,因为你不必一次分配所有的东西。

除了两者都是可迭代的,它们几乎不一样。数组是数据结构,生成器不是。

冷正信
2023-03-14

区别在于效率。例如,PHP以外的许多语言都包含两个range函数,range()xrange()。这是发电机的一个很好的例子,为什么要使用它们。让我们建立自己的:

function range($start, $end) {
    $array = array();
    for ($i = $start; $i <= $end; $i++) {
        $array[] = $i;
    }
    return $array;
}

这真的很直接。然而,对于大范围,它需要大量的内存。如果我们试图用$start=0$end=100000000运行它,我们可能会运行内存溢出!

但是如果我们使用发电机:

function xrange($start, $end) {
    for ($i = $start; $i <= $end; $i++) {
        yield $i;
    }
}

现在我们使用常量内存,但仍然有一个“数组”(如结构),我们可以在同一个空间中迭代(并与其他迭代器一起使用)。

它不会取代阵列,但它确实提供了一种避免需要内存的有效方法。。。

但它也在生成项目方面提供了节省。因为每个结果都是根据需要生成的,所以您可以延迟每个元素的执行(获取或计算),直到您需要它为止。例如,如果您需要从数据库中获取一个项目,并对每一行进行一些复杂的处理,您可以使用生成器将其延迟,直到您实际需要该行:

function fetchFromDb($result) {
    while ($row = $result->fetchArray()) {
        $record = doSomeComplexProcessing($row);
        yield $record;
    }
}

因此,如果只需要前3个结果,则只需处理前3个记录。

为了了解更多信息,我写了一篇关于这个主题的博客文章。

 类似资料:
  • 今天,PHP团队发布了PHP5.5。0版本,其中包括对生成器的支持。在阅读文档时,我注意到它所能做的正是使用数组所能做的。 PHP团队生成器示例: 结果: 但是我可以用数组做同样的事情。我仍然可以与早期版本的PHP保持兼容。 看一看: 那么问题来了:这个新功能存在的目的是什么?我得发挥所有的例子留档不使用新功能,用数组取代它。 有人能给出一个很好的解释,也许是一个例子,在旧版本中不一定是不可能的,

  • 问题内容: 迭代器和生成器有什么区别?有关何时使用每种情况的一些示例会有所帮助。 问题答案: 是一个更笼统的概念:其类具有next方法(在Python 3中)和具有方法的任何对象。 每个生成器都是一个迭代器,但反之亦然。生成器是通过调用具有一个或多个yield表达式(yield在Python 2.5及更早版本中为语句)的函数而构建的,并且该函数是满足上一段对的定义的对象。 当你需要一个具有某些复杂

  • 在Java 7之前,JVM内存中有一个名为PermGen的区域,JVM以前在这里保存它的类。在Java 8中,它被移除并被称为元空间的区域所取代。 PermGen和Metaspace之间最重要的区别是什么? 我知道的唯一区别是,并且忽略了VM参数。

  • 和之间有什么区别? 是什么原因导致他们被扔?如何解决这些问题? 在修改现有代码以包含新的jar文件时,我经常会遇到这些可抛物。我在通过WebStart发布的一个Java应用程序的客户端和服务器端都碰到了它们。 我遇到的可能原因是: 代码客户端的中未包含的包 我们正在使用的新JAR缺少运行时类路径 版本与以前的JAR冲突 当我今天遇到这些问题时,我会采取跟踪和错误的方法来使事情正常工作。我需要更多的

  • 当我试图在Spring4.x上进行测试时,我使用了MockMvc web客户端,但我正在阅读和尝试Spring5.x的新特性。 我认为,WebTestClient和MockMvc是相同或非常相似的。 MockMvc和WebTestClient之间的区别是什么?

  • 有人能给我解释一下map和flatMap之间的区别,以及什么是各自的好用例吗? “结果扁平化”是什么意思?它有什么好处?