2番目の例はまだ期待される動作です... 「参照による」を使用しない限り、実際の配列値ではなく、配列とその値のコピーで作業しています。
foreach( $arr as $x => &$line){
if( preg_match("/word$/", $line)){
$line = preg_replace( "/word$/", '', $line);
$arr[$x+1] = 'word ' . $arr[$x+1];
}
}
unset($line);
$ lineではなく&$ lineを使用していることに注意してください。ループが終了した後は、設定を解除するのが常に最も安全です。
編集
PHPマニュアルからの引用:
注:配列が参照されていない限り、foreachは、配列自体ではなく、指定された配列のコピーを操作します。foreachは、配列ポインターにいくつかの副作用があります。foreachの実行中または実行後に、リセットせずに配列ポインターに依存しないでください。
編集
foreach()での参照の使用はお勧めしません。これは非常に遅く、私の場合は16倍遅くなりました。この行を追加するための解決策:$ line = $ arr [$ x]; ループの始めに、それはいくつかの魔法のトリックをしているようで、すべてが私が期待するように機能します
本当に魔法のトリックではありません。foreachループを介して抽出された$lineの値を、キー($ x)を介して配列から直接$lineで上書きするだけです。
YMMVですが、私にはそれほど遅くは見えません。
次のテストスクリプト:
$arr = range(1,9999);
$callStartTime = microtime(true);
foreach($arr as &$line) {
$line += 1;
}
unset($line);
$callEndTime = microtime(true);
$callTime = $callEndTime - $callStartTime;
echo '<br />Call time to access by reference was '.sprintf('%.4f',$callTime)." seconds<br />\n";
foreach($arr as $x => &$line) {
$line += 1;
}
unset($line);
$callEndTime = microtime(true);
$callTime = $callEndTime - $callStartTime;
echo '<br />Call time to access by reference (retrieving key as well) was '.sprintf('%.4f',$callTime)." seconds<br />\n";
$callStartTime = microtime(true);
foreach($arr as $x => $line) {
$arr[$x] += 1;
}
unset($line);
$callEndTime = microtime(true);
$callTime = $callEndTime - $callStartTime;
echo '<br />Call time and then access array element directly was '.sprintf('%.4f',$callTime)." seconds<br />\n";
$callStartTime = microtime(true);
foreach(array_keys($arr) as $x) {
$arr[$x] += 1;
}
$callEndTime = microtime(true);
$callTime = $callEndTime - $callStartTime;
echo '<br />Call time to access array_keys was '.sprintf('%.4f',$callTime)." seconds<br />\n";
次のタイミングを返します。
Call time to access by reference was 0.0018 seconds
Call time to access by reference (retrieving key as well) was 0.0039 seconds
Call time to access key and then access array element directly was 0.0077 seconds
Call time to access array_keys was 0.0071 seconds