yield生成器是php5.5之後出現的,yield提供了一種更容易的方法來實現簡單的迭代對象,相比較定義類實現 Iterator 接口的方式,性能開銷和複雜性大大降低。
yield生成器允許你 在 foreach 代碼塊中寫代碼來迭代一組數據而不需要在內存中創建一個數組。
對比:
function gettime($num) {
$data=[];
for($i=0;$i<$num;$i++) {
$data[] = time();
}
return $data;
}
foreach (gettime(3) as $v) {
echo $v.PHP_EOL;
sleep(1);
}
//輸出結果如下:
1577710522
1577710522
1577710522
使用迭代器yield:
function gettime($num) {
for($i=0;$i<$num;$i++) {
yield time();
}
}
foreach (gettime(3) as $v) {
echo $v.PHP_EOL;
sleep(1);
}
//輸出結果如下
1577710705
1577710706
1577710707
對比結果發現。使用yield生成的結果是在,被外部調用時才生成。數據不是存於數組中,而是每被調用一次生成一個數據。在處理大數據是,可以明顯減少內存的使用
實際的應用場景
1.讀取超大文件
header("content-type:text/html;charset=utf-8");
function readTxt()
{
$handle = fopen("./test.txt", 'rb');
while (feof($handle)===false) {
yield fgets($handle);
}
fclose($handle);
}
foreach (readTxt() as $key => $value) {
# code...
echo $value.'<br />';
}
2.處理超大數據
如:求k的次方相加
k0+k1+k2+……+kn
function squares($k, $n) {
static $res=1;
for ($i=0;$i<$n;$i++){
yield $res *= $k;
}
}
$num =1;
foreach (squares(2,1000) as $v) {
$num += $v;
}
echo $num;die;
yield輸出的鍵值對
function squares($start, $stop) {
if ($start < $stop) {
for ($i = $start; $i <= $stop; $i++) {
yield $i => $i * $i;
}
}
else {
for ($i = $start; $i >= $stop; $i--) {
yield $i => $i * $i; //迭代生成數組: 鍵=》值
}
}
}
foreach (squares(3, 5) as $n => $square) {
echo $n . ' squared is ' . $square .PHP_EOL;
}