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

PHP 多維陣列搜尋完整指南 (鍵值/鍵名/遞歸)

     編輯:PHP 相關知識

前言

PHP 內建 in_array()、array_search() 僅支援一維陣列。本文整理多維陣列搜尋的多種方案:從簡單的鍵名檢查到完整的遞歸搜尋鍵值/鍵名,並提供可直接使用的通用函式。

一維陣列基礎搜尋回顧

函式用途回傳值範例
in_array($needle, $haystack, $strict)檢查值是否存在boolin_array('Glenn', $people)
array_key_exists($key, $array)檢查鍵名是否存在boolarray_key_exists('apple', $fruit)
array_search($needle, $haystack, $strict)搜尋值,回傳對應鍵名key|falsearray_search('green', $fruits)
array_keys($array, $search_value)取得所有鍵名 (可依值過濾)arrayarray_keys($fruits, 'red')
array_values($array)取得所有值,重設數字索引arrayarray_values($fruits)

多維陣列搜尋鍵值 (遞歸版) - 回傳所有匹配路徑

/**
 * 遞歸搜尋多維陣列中所有符合 $needle 的值
 * @param mixed $needle  要搜尋的值
 * @param array $haystack 目標陣列
 * @return array 符合的鍵名路徑陣列,每個元素為 [層級1=>鍵1, 層級2=>鍵2, ...]
 */
function array_search_recursive($needle, $haystack) {
    $results = [];
    
    function _search($needle, $haystack, $path, &$results) {
        foreach ($haystack as $key => $value) {
            $current_path = $path + [$key => $key]; // 保持鍵名類型
            
            if (is_array($value)) {
                _search($needle, $value, $current_path, $results);
            } elseif ($value === $needle) { // 嚴格比較
                $results[] = $current_path;
            }
        }
    }
    
    _search($needle, $haystack, [], $results);
    return $results;
}

// 測試資料
$foo = [
    1 => ['a' => ['xx' => 'bar 1'], 'b' => ['xx' => 'bar 2']],
    2 => ['a' => ['bb' => 'bar 3', 'yy' => 'bar 4']],
    3 => ['c' => ['dd' => 'bar 3'], 'f' => ['gg' => 'bar 3']],
    'info' => [1 => 'bar 5']
];

$result = array_search_recursive('bar 3', $foo);
print_r($result);
/* 輸出:
Array (
    [0] => Array ( [1] => 2 [2] => a [3] => bb )
    [1] => Array ( [1] => 3 [2] => c [3] => dd )
    [2] => Array ( [1] => 3 [2] => f [3] => gg )
)
*/

多維陣列搜尋鍵名 - 回傳對應的子陣列

/**
 * 遞歸搜尋多維陣列中所有符合 $key 的鍵名
 * @return array 符合鍵名對應的值 (子陣列或純量)
 */
function array_search_key_recursive($key, $haystack) {
    $results = [];
    
    function _search_key($key, $haystack, &$results) {
        foreach ($haystack as $k => $value) {
            if ($k === $key) {
                $results[] = $value;
            }
            if (is_array($value)) {
                _search_key($key, $value, $results);
            }
        }
    }
    
    _search_key($key, $haystack, $results);
    return $results;
}

// 同樣測試資料
$result = array_search_key_recursive('a', $foo);
print_r($result);
/* 輸出:
Array (
    [0] => Array ( [xx] => bar 1 )
    [1] => Array ( [bb] => bar 3, [yy] => bar 4 )
)
*/

進階版:支援多條件搜尋 (鍵名+鍵值同時匹配)

/**
 * 多維陣列多條件搜尋
 * @param array $conditions ['key' => 'keyname', 'value' => 'val', 'strict' => true]
 * @return array 滿足所有條件的節點路徑
 */
function array_search_multi($haystack, $conditions) {
    $results = [];
    
    function _search($haystack, $conditions, $path, &$results) {
        foreach ($haystack as $key => $value) {
            $match = true;
            
            if (isset($conditions['key']) && $key !== $conditions['key']) $match = false;
            if (isset($conditions['value'])) {
                $cmp = $conditions['strict'] ?? false;
                if ($cmp) { if ($value !== $conditions['value']) $match = false; }
                else { if ($value != $conditions['value']) $match = false; }
            }
            
            if ($match && !isset($conditions['key']) && !isset($conditions['value'])) {
                $match = false; // 至少要有一個條件
            }
            
            if ($match) {
                $results[] = $path + [$key => $key];
            }
            
            if (is_array($value)) {
                _search($value, $conditions, $path + [$key => $key], $results);
            }
        }
    }
    
    _search($haystack, $conditions, [], $results);
    return $results;
}

// 找鍵名為 'a' 且值包含 'bar 3' 的節點
$result = array_search_multi($foo, ['key' => 'a', 'value' => 'bar 3']);

效能優化建議

場景建議方案時間複雜度
頻繁搜尋固定結構陣列建立索引陣列 (鍵名=>路徑映射)O(1) 查詢
單次搜尋、資料量 < 10000遞歸函式即可O(n)
大型資料、需高效能改用資料庫 (SQL WHERE) 或 ElasticsearchO(log n) 或更好
只需判斷存在性使用 array_walk_recursive + 旗標變數O(n) 但可提早中斷

array_walk_recursive 簡易版 (僅判斷存在)

function array_exists_recursive($needle, $haystack, $strict = true) {
    $found = false;
    array_walk_recursive($haystack, function($value, $key) use ($needle, $strict, &$found) {
        if ($found) return; // 已找到,雖無法真正中斷但可跳過後續比對
        if ($strict ? $value === $needle : $value == $needle) {
            $found = true;
        }
    });
    return $found;
}

常見陷阱提醒

  • 參考傳遞:遞歸函式中陣列參考傳遞 (&$results) 避免大量複製
  • 嚴格比較:預設使用 === 避免 0 == 'string' 等隱性轉換
  • 循環引用:陣列包含自我引用會導致無限遞歸,需加入 spl_object_id() 追蹤已訪問節點
  • 記憶體爆炸:超大陣列遞歸可能耗盡記憶體,考慮生成器 (yield) 分批處理
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved