クラス Users からオブジェクトの配列を取得したとしましょう。クラス Users にはプロパティ email が含まれます。ユーザー オブジェクトの配列から電子メール プロパティの配列を作成するにはどうすればよいですか?
以下よりも優れた/高速な方法はありますか?
$emails = array();
foreach($users as $user) {
$emails[] = $user->email;
}
C でループを実行する which を使用できますarray_map
が、反復ごとに PHP にコールバックする必要があります。
$emails = array_map(function ($user) { return $user->email; }, $users);
より良い?
上記のコードは、私やおそらくほとんどの関数型プログラマーにとってより表現力豊かですが、それは主観的なものです。また、コールバックには PHP 5.3 が必要です。PHP 5.2 以下では、グローバル関数を宣言することでこれを回避できますが、その場合、特にコードがクラスに表示される場合に、明確さの多くが失われます。
function getUserEmail($user) { return $user->email; }
$emails = array_map('getUserEmail', $users);
もっと早く?
コールバックを使用したこの単純なケースでは、遅いようです (Esben の回答を参照)。ただし、ここで 2 つの注意点があります。
マイクロベンチマークは気難しいことで有名です。それらはマシンごとに異なり、インタープリターの特定のビルドに依存します。さらに悪いことに、このような小さな値の測定は、プロセッサのマルチタスキングやメモリ管理などの他のタスクによって影が薄くなる可能性があります。また、コールバックとグローバル関数を使用する場合でも、時間はかなり異なります。
開発者の時間は、CPU サイクルよりもはるかにコストがかかります。最初に最も簡単にコーディングして保守できるソリューションを作成し、a) 問題があることがわかり、b) 問題がどの程度かを測定した後でのみ最適化する方がよいでしょう。明らかに、これはこの単純なケースではそれほど重要ではありませんが、従うことを学んだ一般的なルールです。
foreach ループが最速のようです。構文は好みの問題だと思います。
編集
David の投稿への返信で述べたように、私は実際にこれをベンチマークしました。
for($i = 0;$i<=8000;$i++){
$users[] = (object)array("email"=>rand(0,15));
}
$arrMapBm = new nzpBM("arrMap");
$foreachBm = new nzpBM("foreach");
$arrMapBm->start();
$emails = array_map(function ($user) { return $user->email; }, $users);
echo $arrMapBm;
unset($emails);
$foreachBm->start();
foreach($users as $user) {
$emails[] = $user->email;
}
echo $foreachBm;
かなり堅実な結果をもたらします。
The benchmark "arrMap (1)" took 4.8160552978516 miliseconds
The benchmark "foreach (1)" took 2.1059513092041 miliseconds
これが現在Windowsマシンを使用しているためかどうかはわかりませんが、私にとっては、array_mapは明らかに高速ではありません。ここで誰かを誤解させようとしているわけではありません。