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

PHP 高效合併兩個關聯數組:告別雙層循環,巧用鍵值索引提升性能

     編輯:PHP 相關知識

在 PHP 開發中,經常需要將兩個關聯數組根據某個共同字段(如 id)進行合併,類似於 SQL 的 LEFT JOIN 操作。最直觀的寫法是使用雙層 foreach 循環遍歷匹配,但這種做法時間複雜度為 O(n×m),數據量大時性能極差。本文介紹一種利用「數組下標索引」的優化方案,將時間複雜度降至 O(n+m),大幅提升執行效率。

問題場景

假設有兩個從數據庫查詢得到的數組:

$test1 = [
    0 => ['id' => 9478137, 'create_time' => 1394760724],
    1 => ['id' => 9478138, 'create_time' => 1394760725],
    2 => ['id' => 9478138, 'create_time' => 1394760725]
];

$test2 = [
    0 => ['id' => 9478137, 'message' => 'love you'],
    1 => ['id' => 9478138, 'message' => 'miss you']
];

需求:以 $test1 為主表,根據 id 字段將 $test2 的 message 合併進去,保留 $test1 的所有記錄(即使重複 id 也要全部保留),類似 LEFT JOIN 效果。

低效寫法:雙層循環

function _mergerArray($array1, $array2, $field1, $field2 = '') {
    $ret = [];
    foreach ($array1 as $key1 => $value1) {
        foreach ($array2 as $key2 => $value2) {
            if ($value1[$field1] == $value2[$field2]) {
                $ret[$key1] = array_merge($value1, $value2);
            }
        }
    }
    return $ret;
}

缺點:每條 $array1 記錄都要遍歷整個 $array2,數據量達萬級時明顯卡頓。

優化方案:建立索引映射,單次遍歷合併

核心思路:先遍歷 $array2,以關聯字段值為鍵建立「查找表」;再遍歷 $array1 直接通過鍵值 O(1) 取得對應數據並合併。

function _mergerArray($array1, $array2, $field1, $field2 = '') {
    $ret = [];
    $field2 = $field2 ?: $field1; // 若未指定 field2,默認與 field1 相同

    // 步驟 1:將 $array2 轉為「鍵值 => 完整記錄」的映射表
    $lookup = [];
    foreach ($array2 as $item) {
        $lookup[$item[$field1]] = $item;
    }

    // 步驟 2:遍歷 $array1,直接通過鍵值合併
    foreach ($array1 as $item) {
        $key = $item[$field1];
        if (isset($lookup[$key])) {
            $ret[] = array_merge($lookup[$key], $item);
        } else {
            $ret[] = $item; // 無匹配時保留原記錄(LEFT JOIN 語義)
        }
    }
    return $ret;
}

// 測試
$ret = _mergerArray($test1, $test2, 'id', 'id');
print_r($ret);

輸出結果

Array
(
    [0] => Array
        (
            [id] => 9478137
            [message] => love you
            [create_time] => 1394760724
        )
    [1] => Array
        (
            [id] => 9478138
            [message] => miss you
            [create_time] => 1394760725
        )
    [2] => Array
        (
            [id] => 9478138
            [message] => miss you
            [create_time] => 1394760725
        )
)

完全符合 LEFT JOIN 預期:$test1 的三條記錄全部保留,重複 id 也各自合併了對應的 message。

性能對比與適用場景

  • 雙層循環:O(n×m),適合極小數據集(<100 條)或一次性腳本。
  • 索引映射法:O(n+m),適合常規業務邏輯、中大型數據集,推薦作為通用工具函數。

若 $array2 存在重複鍵值,後出現的記錄會覆蓋先前的(類似 SQL 中無唯一約束時的行為),可根據業務需求調整為保留首條或合併為數組。

總結

「以空間換時間」是經典優化策略。將關聯數組轉為鍵值索引映射,避免了重複遍歷,代碼簡潔且性能穩健。下次遇到數組 JOIN 需求,請優先考慮此模式。

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