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

PHP 遞歸處理多維數組的實用技巧

     編輯:PHP 相關知識

場景介紹

處理多維數組(嵌套數組)時,遞歸是最自然的遍歷與轉換方式。本文通過「HTML 特殊字符轉義」實例,演示遞歸處理多維數組的核心模式與變體。

核心示例:多維數組字符替換

<?php
// 原始數據:包含嵌套數組的混合結構
$arr = [
    ['< 小剛>', '< 小曉>'],
    '< 小飛>',
    '< 小李>',
    '< 小紅>'
];

/**
 * 遞歸處理數組中的字符串值
 * @param mixed $value 數組或標量值
 * @return mixed 處理後的值(保持原結構)
 */
function arrContentReplact($value) {
    // 基線條件:非數組直接處理
    if (!is_array($value)) {
        return str_replace(['<', '>'], ['{', '}'], $value);
    }
    
    // 遞歸條件:遍歷數組元素
    foreach ($value as $key => $item) {
        // 關鍵:引用賦值保持原數組結構
        $value[$key] = arrContentReplact($item);
    }
    
    return $value;
}

// 執行處理
$arr3 = arrContentReplact($arr);

// 輸出結果
echo "<pre>";
print_r($arr3);
echo "</pre>";
/*
輸出結果:
Array
(
    [0] => Array
        (
            [0] => { 小剛}
            [1] => { 小曉}
        )
    [1] => { 小飛}
    [2] => { 小李}
    [3] => { 小紅}
)
*/
?>

遞歸核心模式解析

<?php
/**
 * 通用遞歸數組處理模板
 */
function recursiveArrayProcess($data, callable $scalarHandler, callable $arrayHandler = null) {
    if (is_array($data)) {
        $result = [];
        foreach ($data as $key => $value) {
            // 遞歸處理子元素
            $processed = recursiveArrayProcess($value, $scalarHandler, $arrayHandler);
            
            // 可選:數組層級處理(如過濾、排序、鍵名轉換)
            if ($arrayHandler) {
                $processed = $arrayHandler($key, $processed);
            }
            
            $result[$key] = $processed;
        }
        return $result;
    }
    
    // 標量值處理
    return $scalarHandler($data);
}

// 使用示例:同樣的字符替換
$processed = recursiveArrayProcess($arr, function($scalar) {
    return str_replace(['<', '>'], ['{', '}'], $scalar);
});
?>

進階變體與實用技巧

1. 引用傳遞修改原數組(節省內存)

<?php
function arrayWalkRecursiveRef(array &$array, callable $callback) {
    array_walk_recursive($array, function(&$value, $key) use ($callback) {
        $value = $callback($value, $key);
    });
}

// 使用
arrayWalkRecursiveRef($arr, function(&$value) {
    $value = str_replace(['<', '>'], ['{', '}'], $value);
});
// $arr 直接被修改
?>

2. 保留鍵名的扁平化

<?php
function flattenArray(array $array, string $prefix = ''): array {
    $result = [];
    foreach ($array as $key => $value) {
        $newKey = $prefix ? "$prefix.$key" : (string)$key;
        if (is_array($value)) {
            $result = array_merge($result, flattenArray($value, $newKey));
        } else {
            $result[$newKey] = $value;
        }
    }
    return $result;
}

// 輸出: ['0.0' => '{ 小剛}', '0.1' => '{ 小曉}', '1' => '{ 小飛}', ...]
?>

3. 深度限制防棧溢出

<?php
function recursiveWithDepthLimit($data, callable $fn, int $maxDepth = 100, int $currentDepth = 0) {
    if ($currentDepth >= $maxDepth) {
        throw new RuntimeException("遞歸深度超過限制: $maxDepth");
    }
    
    if (is_array($data)) {
        foreach ($data as $key => $value) {
            $data[$key] = recursiveWithDepthLimit($value, $fn, $maxDepth, $currentDepth + 1);
        }
        return $data;
    }
    return $fn($data);
}
?>

4. 生成器版本(內存極優)

<?php
function recursiveGenerator($data) {
    if (is_array($data)) {
        foreach ($data as $value) {
            yield from recursiveGenerator($value);
        }
    } else {
        yield $data;
    }
}

// 只遍歷不構建新數組,極省內存
foreach (recursiveGenerator($hugeArray) as $scalar) {
    processScalar($scalar);
}
?>

常見遞歸任務封裝庫

<?php
class ArrayRecursive {
    /** 映射:對每個標量值應用回調 */
    public static function map(array $array, callable $callback): array {
        return array_map(function($v) use ($callback) {
            return is_array($v) ? self::map($v, $callback) : $callback($v);
        }, $array);
    }
    
    /** 遍歷:對每個標量值執行回調(不改變結構) */
    public static function walk(array &$array, callable $callback): void {
        array_walk_recursive($array, $callback);
    }
    
    /** 過濾:移除不符合條件的標量值(保留結構) */
    public static function filter(array $array, callable $callback): array {
        return array_filter($array, function($v) use ($callback) {
            return is_array($v) ? !empty(self::filter($v, $callback)) : $callback($v);
        });
    }
    
    /** 搜索:查找滿足條件的首個值路徑 */
    public static function search(array $array, callable $callback): ?array {
        foreach ($array as $key => $value) {
            if (is_array($value)) {
                if ($path = self::search($value, $callback)) {
                    return array_merge([$key], $path);
                }
            } elseif ($callback($value, $key)) {
                return [$key];
            }
        }
        return null;
    }
    
    /** 扁平化:多維轉一維(鍵名用分隔符連接) */
    public static function flatten(array $array, string $separator = '.'): array {
        $result = [];
        $iterator = new RecursiveIteratorIterator(
            new RecursiveArrayIterator($array),
            RecursiveIteratorIterator::SELF_FIRST
        );
        foreach ($iterator as $key => $value) {
            if (!$iterator->hasChildren()) {
                $path = [];
                for ($i = 0; $i <= $iterator->getDepth(); $i++) {
                    $path[] = $iterator->getSubIterator($i)->key();
                }
                $result[implode($separator, $path)] = $value;
            }
        }
        return $result;
    }
}

// 使用
$clean = ArrayRecursive::map($dirtyArr, fn($v) => htmlspecialchars($v, ENT_QUOTES, 'UTF-8'));
$flat = ArrayRecursive::flatten($nestedConfig);
?>

性能與棧溢出防範

方案最大深度內存效率適用場景
原生遞歸函數~100-200 (PHP 默認棧)中等淺層嵌套、簡單邏輯
array_walk_recursive同上高(原地修改)只需修改值、不改結構
RecursiveIteratorIterator無限制(堆內存)高(迭代器)深層嵌套、大數據量
生成器 yield from無限制極高(懶加載)只需遍歷、不構建結果
手動棧模擬遞歸無限制可控極深嵌套、需精確控制

手動棧遞歸(無棧溢出風險)

<?php
function iterativeArrayProcess(array $array, callable $scalarFn): array {
    $stack = [['array' => &$array, 'keys' => []]];
    $result = [];
    $refs = [&$result]; // 引用鏈
    
    while ($stack) {
        $frame = array_pop($stack);
        $currentArray = &$frame['array'];
        $currentKeys = $frame['keys'];
        
        foreach ($currentArray as $key => &$value) {
            $newKeys = array_merge($currentKeys, [$key]);
            
            if (is_array($value)) {
                // 創建結果數組的引用位置
                $target = &$result;
                foreach ($newKeys as $k) {
                    if (!isset($target[$k])) $target[$k] = [];
                    $target = &$target[$k];
                }
                $stack[] = ['array' => &$value, 'keys' => $newKeys];
            } else {
                // 設置處理後的值
                $target = &$result;
                foreach ($newKeys as $k) {
                    $target = &$target[$k];
                }
                $target = $scalarFn($value);
            }
        }
    }
    return $result;
}
?>

總結

PHP 處理多維數組遞歸的核心模式是:「判斷類型 → 標量處理 / 數組遞歸 → 組合結果」。現代開發優先選擇 RecursiveIteratorIterator 或 array_walk_recursive,複雜邏輯封裝為工具類。注意棧深度限制,大數據量改用迭代器或生成器模式。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved