PHPジェネレーター徹底解説!yieldキーワードでメモリ効率の良い反復処理を実現する方法
はじめに
foreach などのループ構文で大規模なデータコレクションを走査する場合、大量のメモリと相当な処理時間が必要になります。ジェネレータ(Generator)を使えば、こうしたオーバーヘッドなしにデータセットを反復処理できます。
ジェネレータ関数は普通の関数とよく似ています。ただし、通常の関数が return 文で値を返すのに対し、ジェネレータは yield キーワードを使用し、繰り返し実行されながらイテレーション用の値を順次提供します。
yield キーワードこそがジェネレータ機構の心臓部です。使い方は return と似ていますが、関数の実行を終了させるわけではありません。次のイテレーション用の値を返したうえで、関数の実行をその場で一時停止します。
値をyieldする
ジェネレータ関数の中では、for ループなどでループ変数の各値を順番に yield していきます。
例1:平方数を生成するジェネレータ
<?php
function squaregenerator(){
for ($i=1; $i<=5; $i++){
yield $i*$i;
}
}
$gen = squaregenerator();
foreach ($gen as $val){
echo $val . " ";
}
?>
foreach 文が最初に $val を表示しようとすると、squaregenerator() は最初の要素を yield し、変数 $i の状態を保持したまま実行を一時停止します。そして foreach が次の反復に入ると、停止していた位置から処理を再開します。出力は通常の foreach ループと同じようになります。
出力結果
1 4 9 16 25
例2:range() 関数をジェネレータで実装
PHP の組み込み関数 range() は、開始値から終了値までを指定したステップ間隔で整数のリストを返します。次のプログラムは、この range() をジェネレータで実装したものです。
<?php
function rangegenerator($start, $stop, $step){
for ($i=$start; $i<=$stop; $i+=$step){
yield $i;
}
}
foreach (rangegenerator(2,10,2) as $val){
echo $val . " ";
}
?>
出力結果
出力は range(2,10,2) を使った場合と同じになります。
2 4 6 8 10
例3:連想配列をジェネレータで処理
連想配列もジェネレータで扱うことができます。キーと値のペアを $key => $val の形式で yield すれば、foreach 側でもキーと値を同時に受け取れます。
<?php
function arrgenerator($arr){
foreach ($arr as $key=>$val){
yield $key=>$val;
}
}
$arr = array("one"=>1, "two"=>2, "three"=>3, "four"=>4);
$gen = arrgenerator($arr);
foreach ($gen as $key=>$val)
echo $key . "=>" . $val . "\n";
?>
出力結果
one=>1 two=>2 three=>3 four=>4
まとめ
ジェネレータを使う最大のメリットはメモリ効率です。すべての値を配列として事前に生成して保持する必要がないため、巨大なデータセットや逐次生成されるデータの処理でもメモリ消費を最小限に抑えられます。PHP 5.5 以降で利用できる機能なので、大規模データの反復処理が必要な場面では積極的に活用しましょう。
-
PHPのlog()関数とは?自然対数の計算方法と使い方を解説
定義と使い方log() 関数は、数値の自然対数(natural logarithm)を計算します。対数とは、指数関数の逆演算のことです。たとえば 102=100 という関係は「log10100=2」と表せます。自然対数はオイラー数 e を底として計算され、PHP では定義済み定数 M_E によって e の値(2.7182818284590452354)が提供されています。具体例を挙げると、exp(4.60517018599)=100(つまり e4.60517018599=100)が成り立つため、loge100=4.60517018599 となります。PHP では、この自然対数(loge)を l
-
PHPのis_nan()関数とは?使い方と実行例をわかりやすく解説
PHPのis_nan()関数は、引数として渡された値が「NAN(Not A Number:非数)」であるかどうかを判定するための関数です。数値演算の結果が不正な値になったかどうかを確認したい場合に役立ちます。 定義と使い方 NANは「Not A Number(非数)」の略で、数学的に定義できない数値演算の結果などを表します。is_nan()関数は、引数がNANであるかどうかをチェックし、その結果をブール値(true / false)で返します。 構文 is_nan ( float $val ) : bool パラメータ No.パラメータと説明 1 valNANであるかどうかを検証する