今天,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";
}
那么问题来了:这个新功能存在的目的是什么?我得发挥所有的例子留档不使用新功能,用数组取代它。
有人能给出一个很好的解释,也许是一个例子,在旧版本中不一定是不可能的,但是使用生成器可以帮助开发吗?
数组必须包含在开始循环之前循环的每个值;生成器根据请求“动态”创建每个值,因此内存要少得多;
数组与它包含的值一起工作,并且必须预先填充这些值;生成器可以根据直接使用的特殊标准创建值...例如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, ' ';
}
生成器允许延迟计算复杂语句。这样你就节省了内存,因为你不必一次分配所有的东西。
除了两者都是可迭代的,它们几乎不一样。数组是数据结构,生成器不是。
区别在于效率。例如,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之间的区别,以及什么是各自的好用例吗? “结果扁平化”是什么意思?它有什么好处?