PHP 5.5.0

Generator 是一個簡單版Iterator,不同的是不需要實作 Iterator
只有在需要的時候計算並產生迭代的數值,減少佔用記憶體空間。

Generators

  • 使用 yield 關鍵字
<?php
function myGenerator()
{
yield 'value1';
yield 'value2';
yield 'value3';
}

foreach (myGenerator() as $yieldValue) {
echo $yieldValue , PHP_EOL;
}

/**
* Result:
* value1
* value2
* value2
*/

Generator 不是解決 Iterator 的萬靈藥,
不會知道下一個迭代值,只能用它進行往前的迭代,
用過即丟,無法利用同一個 Generator 重複迭代。

方法比較

方法1: 如果都沒有使用 Iterator, Generator

<?php
function getLines($fileName)
{
$lines = [];
$file = fopen($fileName, 'r');
while (!feof($file)) {
$lines[] = fgets($file);
}
fclose($file);
return $lines;
}

foreach (getLines('myFile') as $line) {
echo $line , PHP_EOL;
}

檔案小還好,如果檔案大到GB,記憶體可能就會不足

 

方法2: 用 Iterator

<?php
class FileIterator implements Iterator
{
protected $file;
protected $key = 0;
protected $current;

public function __construct($file)
{
$this->file = fopen($file, 'r');
}

public function __destruct()
{
fclose($this->file);
}

public function current()
{
return $this->current;
}

public function key()
{
return $this->key;
}

public function next()
{
$this->current = fgets($this->file);
}

public function rewind()
{
rewind($this->file);
$this->current = fgets($this->file);
$this->key = 0;
}

public function valid()
{
return !feof($this->file);
}

}

$file = new FileIterator('myFile');
foreach ($file as $line) {
echo $line , PHP_EOL;
}

要實作必須寫一堆 method ,符合 Iterator 介面

 

方法3: 用 Generator

<?php

function getLines($fileName)
{
$file = fopen($fileName, 'r');
while (!feof($file)) {
yield fgets($file);
}
}

foreach (getLines('myFile') as $line) {
echo $line , PHP_EOL;
}

簡潔很多,但無法知道下一個迭代值,只能向前迭代

參考資料