PHP 提供多種陣列遍歷方式,各有語義差異與性能特點。本文系統對比 foreach、for、while+list+each、key、遞歸遍歷,給出選型建議與最佳實踐。
| 方式 | 適用場景 | 鍵值獲取 | 內部指針 | 性能 | 修改原陣列 |
|---|---|---|---|---|---|
| foreach | 絕大多數場景 | $k => $v / $v | 不影響 | 最快 | 值傳遞(引用可修改) |
| for | 數值索引、需索引運算 | $i => $arr[$i] | 不影響 | 快 | 直接修改 |
| while+list+each | 歷史代碼、需手動控制指針 | list($k,$v) | 前移 | 慢 | 直接修改 |
| key/next/current | 極少數底層控制 | key() / current() | 手動 | 最慢 | 直接修改 |
$colors = ['red', 'blue', 'green'];
// 僅值
foreach ($colors as $color) { ... }
// 鍵值
foreach ($colors as $key => $color) { ... }
// 引用修改原陣列
foreach ($data as &$row) {
$row['processed'] = true;
}
unset($row); // 重要:斷開引用
&);unset($arr[$key]) 導致跳過元素,改用 array_filter。$arr = ['zero', 'one', 'two'];
for ($i = 0, $len = count($arr); $i < $len; $i++) {
echo $arr[$i];
}
// 反向遍歷
for ($i = count($arr) - 1; $i >= 0; $i--) { ... }
array_values 重建);$colors = ['red', 'blue', 'green'];
reset($colors); // 重置指針
while (list($key, $val) = each($colors)) {
echo "$key => $val\n";
}
each() 返回 [1=>val, 'value'=>val, 0=>key, 'key'=>key];foreach。$capitals = ['Ohio' => 'Columbus', 'Iowa' => 'Des Moines'];
while ($key = key($capitals)) {
echo $key . "\n";
next($capitals); // 必須手動前移
}
key() 不移動指針,需配合 next();function array_recursive_iter(array $arr, callable $callback, int $depth = 0): void {
foreach ($arr as $key => $val) {
if (is_array($val)) {
array_recursive_iter($val, $callback, $depth + 1);
} else {
$callback($key, $val, $depth);
}
}
}
// 使用:扁平化輸出所有葉子值
$flat = [];
array_recursive_iter($data, function($k, $v) use (&$flat) {
$flat[] = $v;
});
$it = new RecursiveIteratorIterator(new RecursiveArrayIterator($data));
foreach ($it as $key => $val) {
echo str_repeat(' ', $it->getDepth()) . "$key => $val\n";
}
// 過濾葉子節點
$leaves = new RegexIterator($it, '/./', RecursiveRegexIterator::GET_MATCH);
| 方法 | 耗時 (ms) | 記憶體 |
|---|---|---|
| foreach (值) | ~45 | 基線 |
| foreach (引用) | ~50 | +微增 |
| for | ~55 | 基線 |
| while+each | ~120 | +顯著 |
| RecursiveIteratorIterator | ~80 | +物件開銷 |
foreach,語義清晰、性能最優;for;RecursiveIteratorIterator,避免棧溢出、代碼更健壯;each()/list(),PHP 8 已移除;unset($ref),防止殘留引用污染後續邏輯;function gen() { foreach($huge as $v) yield $v; } 分塊處理。 選對遍歷方式,代碼更簡潔、性能更優、維護更易。