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

PHP 陣列合併與遞迴合併完整指南:array_merge vs array_merge_recursive

     編輯:PHP 相關知識

PHP 提供多種陣列合併函式,行為差異大,選錯易導致資料遺失或結構錯誤。本文深入對比 array_merge()、array_merge_recursive()、+ 運算子、array_replace()、array_replace_recursive() 的關鍵差異,並提供選型決策表。

一、核心函式行為對比

1. array_merge() - 重新索引、後者覆蓋字串鍵

$a = ['a' => 'apple', 'b' => 'banana'];
$b = ['b' => 'blueberry', 'c' => 'cherry'];
print_r(array_merge($a, $b));
/*
Array
(
    [a] => apple
    [b] => blueberry  ← 字串鍵 'b' 被覆蓋
    [c] => cherry
)
*/

// 數值鍵會重新索引 (0,1,2...)
$arr1 = [10 => 'x', 20 => 'y'];
$arr2 = [30 => 'z'];
print_r(array_merge($arr1, $arr2));
// Array ( [0] => x, [1] => y, [2] => z )

2. array_merge_recursive() - 字串鍵相同則建立巢狀陣列

$a = ['color' => 'red', 'fruit' => 'apple'];
$b = ['color' => 'green', 'size' => 'large'];
print_r(array_merge_recursive($a, $b));
/*
Array
(
    [color] => Array ( [0] => red, [1] => green )  ← 合併為陣列
    [fruit] => apple
    [size]  => large
)
*/

3. + 運算子 (聯集) - 保留第一個陣列的鍵,忽略後者相同鍵

$a = ['a' => 'apple', 'b' => 'banana'];
$b = ['b' => 'blueberry', 'c' => 'cherry'];
print_r($a + $b);
/*
Array
(
    [a] => apple
    [b] => banana   ← 保留 $a 的值
    [c] => cherry
)
*/

4. array_replace() - 類似 merge 但不重新索引數值鍵

$a = [10 => 'x', 20 => 'y'];
$b = [20 => 'z', 30 => 'w'];
print_r(array_replace($a, $b));
// Array ( [10] => x, [20] => z, [30] => w )  ← 鍵 20 保留

5. array_replace_recursive() - 遞迴版 replace

$a = ['config' => ['debug' => true, 'log' => 'daily']];
$b = ['config' => ['debug' => false, 'cache' => 'redis']];
print_r(array_replace_recursive($a, $b));
/*
Array
(
    [config] => Array
        (
            [debug] => false   ← 覆蓋
            [log]   => daily   ← 保留
            [cache] => redis   ← 新增
        )
)
*/

二、選型決策表

需求推薦函式關鍵行為
一般合併,字串鍵後者勝出,數值鍵重新索引array_merge()最常用、行為直覺
字串鍵衝突需**保留所有值** (建立陣列)array_merge_recursive()配置合併、多值欄位
**保留第一個陣列的值**,忽略後者同鍵$a + $b預設值覆寫、優先級合併
保留數值鍵不重新索引,字串鍵後者勝出array_replace()鍵有業務含義 (如 ID)
多維陣列深度合併,標量值覆蓋,陣列值遞迴合併array_replace_recursive()配置檔案多層覆寫

三、實戰場景範例

場景 1:配置檔案分層覆寫 (預設 → 環境 → 本地)

$default = [
    'app' => ['debug' => false, 'locale' => 'en'],
    'db'  => ['host' => 'localhost', 'port' => 3306],
];
$env = [
    'app' => ['debug' => true],
    'db'  => ['host' => 'db.prod'],
];
$local = [
    'db' => ['port' => 3307],
];

// 深度合併,保留結構
$config = array_replace_recursive($default, $env, $local);
/*
[
    'app' => ['debug' => true, 'locale' => 'en'],
    'db'  => ['host' => 'db.prod', 'port' => 3307],
]
*/

場景 2:表單多選欄位合併 (同名稱多值)

// $_POST['tags'] 可能來自多個來源
$source1 = ['tags' => ['php', 'laravel']];
$source2 = ['tags' => ['mysql']];

// 合併為單一陣列
$merged = array_merge_recursive($source1, $source2);
// ['tags' => ['php', 'laravel', 'mysql']]

// 若用 array_merge 會被覆蓋!
$wrong = array_merge($source1, $source2);
// ['tags' => ['mysql']] ← 資料遺失

場景 3:API 回應預設值填充

$defaults = [
    'page' => 1,
    'per_page' => 15,
    'sort' => 'created_at',
    'order' => 'desc',
];
$userInput = ['page' => 3, 'sort' => 'name']; // 缺少 per_page, order

// 使用者輸入優先,缺少則用預設
$params = $userInput + $defaults;
// ['page' => 3, 'per_page' => 15, 'sort' => 'name', 'order' => 'desc']

四、效能與記憶體考量

  • 所有函式都會**建立新陣列**,不修改原陣列
  • 大型陣列 (10萬+ 元素) 合併會消耗記憶體,考慮分批處理或使用 Generator
  • array_merge_recursive 若深度巢狀極深,可能觸發遞迴限制

五、常見錯誤與除錯

// 錯誤:期望保留數值鍵
$arr1 = [100 => 'a'];
$arr2 = [200 => 'b'];
$result = array_merge($arr1, $arr2);
// 結果: [0 => 'a', 1 => 'b'] ← 鍵遺失!
// 正確: array_replace($arr1, $arr2) 或 $arr1 + $arr2

// 錯誤:多維陣列用 array_merge 導致子陣列被整個覆蓋
$config1 = ['db' => ['host' => 'a', 'port' => 3306]];
$config2 = ['db' => ['port' => 3307]];
array_merge($config1, $config2);
// ['db' => ['port' => 3307]] ← host 遺失!
// 正確: array_replace_recursive($config1, $config2)

六、總結

記住三大核心行為:
1. array_merge = 重新索引 + 字串鍵覆蓋
2. array_merge_recursive = 字串鍵衝突變陣列
3. + = 第一優先,保留原鍵
根據「衝突時要保留誰、鍵是否有意義、是否多層」三個問題選型。

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