首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

PHP 遞迴遍歷多維陣列:簡潔實作與效能考量

     編輯:PHP 相關知識

多維陣列遍歷是常見需求,遞迴是最直觀的解法。本文提供標準遞迴實作、迭代器替代方案與深度過大時的效能優化建議。

遞迴函式標準寫法

<?php
/**
 * 遞迴遍歷多維陣列,印出所有非陣列值
 * @param array $arr
 * @param int $depth 當前深度 (除錯用)
 */
function arrayRecursivePrint(array $arr, int $depth = 0) {
    foreach ($arr as $key => $val) {
        if (is_array($val)) {
            // 可選:印出鍵名層級
            // echo str_repeat('  ', $depth) . "[$key] => Array\n";
            arrayRecursivePrint($val, $depth + 1);
        } else {
            echo str_repeat('  ', $depth) . "[$key] => $val\n";
        }
    }
}

// 測試資料
$data = [
    1 => [11, 12, 13, 14 => [141, 142]],
    2, 3, 4, 5
];

echo "原始結構:\n";
print_r($data);

echo "\n遍歷結果:\n";
arrayRecursivePrint($data);
?>

輸出結果

原始結構:
Array
(
    [1] => Array
        (
            [0] => 11
            [1] => 12
            [2] => 13
            [14] => Array
                (
                    [0] => 141
                    [1] => 142
                )
        )
    [2] => 2
    [3] => 3
    [4] => 4
    [5] => 5
)

遍歷結果:
  [0] => 11
  [1] => 12
  [2] => 13
    [0] => 141
    [1] => 142
[2] => 2
[3] => 3
[4] => 4
[5] => 5

進階需求:保留鍵名路徑 / 收集扁平化陣列

<?php
/**
 * 將多維陣列扁平化為 ['路徑.鍵' => 值]
 */
function arrayFlatten(array $arr, string $prefix = ''): array {
    $result = [];
    foreach ($arr as $key => $val) {
        $newKey = $prefix ? "$prefix.$key" : (string)$key;
        if (is_array($val)) {
            $result = array_merge($result, arrayFlatten($val, $newKey));
        } else {
            $result[$newKey] = $val;
        }
    }
    return $result;
}

print_r(arrayFlatten($data));
/*
輸出:
Array
(
    [1.0] => 11
    [1.1] => 12
    [1.2] => 13
    [1.14.0] => 141
    [1.14.1] => 142
    [2] => 2
    [3] => 3
    [4] => 4
    [5] => 5
)
*/
?>

遞迴深度限制與棧溢位風險

  • PHP 預設無硬性遞迴深度限制,但受 **C 棧大小** 限制 (通常數千層會 Segfault)。
  • `xdebug.max_nesting_level` (預設 256) 會拋出錯誤中斷,生產環境通常關閉 Xdebug。

非遞迴替代方案:RecursiveIteratorIterator (SPL)

<?php
$iterator = new RecursiveIteratorIterator(
    new RecursiveArrayIterator($data),
    RecursiveIteratorIterator::SELF_FIRST // 或 LEAVES_ONLY
);

foreach ($iterator as $key => $val) {
    $depth = $iterator->getDepth();
    echo str_repeat('  ', $depth) . "[$key] => $val\n";
}
?>

**優點**:內建、記憶體效率佳 (迭代器模式)、支援 `getDepth()`、`hasChildren()`、可搭配 `FilterIterator` 過濾。

效能比較與建議

方案適用場景記憶體速度
遞迴函式簡單邏輯、深度 < 100、需自訂處理較高 (呼叫棧)快
SPL 迭代器深度未知、大陣列、需過濾/轉換低 (單次遍歷)中等
手動堆疊模擬極深層級、避免棧溢位可控較慢

手動堆疊模擬遞迴 (避免棧溢位)

<?php
function arrayIterativeFlatten(array $arr): array {
    $stack = [['arr' => $arr, 'prefix' => '']];
    $result = [];

    while ($stack) {
        $frame = array_pop($stack);
        foreach ($frame['arr'] as $key => $val) {
            $newKey = $frame['prefix'] ? $frame['prefix'] . '.' . $key : (string)$key;
            if (is_array($val)) {
                $stack[] = ['arr' => $val, 'prefix' => $newKey];
            } else {
                $result[$newKey] = $val;
            }
        }
    }
    return $result;
}
?>
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved