Ваш второй пример все еще ожидаемое поведение ... Вы работаете над копией массива и его значений, а не фактическими значениями массива , если вы не используете "по ссылке"
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, и всегда безопаснее сбрасывать после завершения цикла
EDIT
Цитата из руководства по PHP :
Примечание. Если на массив не ссылаются,
foreach работает с копией
указанный массив, а не массив
сам. foreach имеет некоторые побочные эффекты
на указатель массива. Не полагайтесь на
указатель массива во время или после
foreach без сброса настроек.
EDIT
Я не рекомендую использовать
ссылки в foreach (), это
очень медленно, в моем случае это было 16x
помедленнее. Решение, чтобы добавить это
строка: $ line = $ arr [$ x]; в
начало цикла, кажется, делает
некоторые фокусы магии и все
работает как я ожидал
Не совсем магический трюк. Он просто перезаписывает значение $ line, извлеченное через цикл foreach, $ line прямо из массива через ключ ($ x).
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