PHP Conference Japan 2024

array_merge_recursive

(PHP 4 >= 4.0.1, PHP 5, PHP 7, PHP 8)

array_merge_recursive遞迴地合併一個或多個陣列

說明

array_merge_recursive(array ...$arrays): array

array_merge_recursive() 將一個或多個陣列的元素合併在一起,使一個陣列的值附加到前一個陣列的末尾。它會返回合併後的陣列。

如果輸入的陣列具有相同的字串鍵,則這些鍵的值會合併到一個陣列中,並且是遞迴地進行,因此如果其中一個值本身也是一個陣列,則該函數也會將其與另一個陣列中的相應條目合併。但是,如果陣列具有相同的數字鍵,則後面的值不會覆寫原始值,而是會被附加。

參數

arrays

要遞迴合併的陣列的變數列表。

返回值

一個將參數合併在一起後產生值的陣列。如果呼叫時沒有任何參數,則會返回一個空的 array

更新日誌

版本 說明
7.4.0 此函數現在可以在沒有任何參數的情況下呼叫。以前,至少需要一個參數。

範例

範例 1 array_merge_recursive() 範例

<?php
$ar1
= array("color" => array("favorite" => "red"), 5);
$ar2 = array(10, "color" => array("favorite" => "green", "blue"));
$result = array_merge_recursive($ar1, $ar2);
print_r($result);
?>

上面的範例會輸出

Array
(
    [color] => Array
        (
            [favorite] => Array
                (
                    [0] => red
                    [1] => green
                )

            [0] => blue
        )

    [0] => 5
    [1] => 10
)

參見

新增筆記

使用者貢獻的筆記 38 個筆記

168
gabriel dot sobrinho at gmail dot com
15 年前
我重構了 Daniel 的函數,我得到了它

<?php
/**
* array_merge_recursive 的確會合併陣列,但它會將具有重複鍵的值轉換為陣列,而不是用第二個陣列中的重複值覆寫第一個陣列中的值,就像 array_merge 那樣。也就是說,使用 array_merge_recursive,會發生這種情況(已記錄的行為):
*
* array_merge_recursive(array('key' => 'org value'), array('key' => 'new value'));
* => array('key' => array('org value', 'new value'));
*
* array_merge_recursive_distinct 不會更改陣列中值的資料型別。
* 第二個陣列中匹配鍵的值會覆寫第一個陣列中的值,就像 array_merge 的情況一樣,也就是說:
*
* array_merge_recursive_distinct(array('key' => 'org value'), array('key' => 'new value'));
* => array('key' => array('new value'));
*
* 參數是透過引用傳遞的,儘管僅出於效能原因。它們不會被此函數修改。
*
* @param array $array1
* @param array $array2
* @return array
* @author Daniel <daniel (at) danielsmedegaardbuus (dot) dk>
* @author Gabriel Sobrinho <gabriel (dot) sobrinho (at) gmail (dot) com>
*/
function array_merge_recursive_distinct ( array &$array1, array &$array2 )
{
$merged = $array1;

foreach (
$array2 as $key => &$value )
{
if (
is_array ( $value ) && isset ( $merged [$key] ) && is_array ( $merged [$key] ) )
{
$merged [$key] = array_merge_recursive_distinct ( $merged [$key], $value );
}
else
{
$merged [$key] = $value;
}
}

return
$merged;
}
?>

當第一個陣列沒有該鍵且第二個陣列具有一個陣列值時,此修復了 E_NOTICE。
25
martyniuk dot vasyl at gmail dot com
12 年前
這是我的 array_merge_recursive 版本,沒有覆寫數字鍵
<?php
function array_merge_recursive_new() {

$arrays = func_get_args();
$base = array_shift($arrays);

foreach (
$arrays as $array) {
reset($base); //important
while (list($key, $value) = @each($array)) {
if (
is_array($value) && @is_array($base[$key])) {
$base[$key] = array_merge_recursive_new($base[$key], $value);
} else {
$base[$key] = $value;
}
}
}

return
$base;
}
?>
11
daniel at danielsmedegaardbuus dot dk
15 年前
<?php
/**
* array_merge_recursive 的確會合併陣列,但它會將具有重複鍵的值轉換為陣列,而不是像 array_merge 那樣,使用第二個陣列中的重複值覆寫第一個陣列中的值。也就是說,使用 array_merge_recursive,會發生以下情況(已記錄的行為):
*
* array_merge_recursive(array('key' => 'org value'), array('key' => 'new value'));
* => array('key' => array('org value', 'new value'));
*
* array_merge_recursive_distinct 不會更改陣列中值的資料類型。
* 第二個陣列中匹配鍵的值會覆寫第一個陣列中的值,這與 array_merge 的情況相同,即:
*
* array_merge_recursive_distinct(array('key' => 'org value'), array('key' => 'new value'));
* => array('key' => array('new value'));
*
* 參數以參考方式傳遞,但僅出於效能考量。它們不會被此函數修改。
*
* @param array $array1
* @param mixed $array2
* @return array
* @author daniel@danielsmedegaardbuus.dk
*/
function &array_merge_recursive_distinct(array &$array1, &$array2 = null)
{
$merged = $array1;

if (
is_array($array2))
foreach (
$array2 as $key => $val)
if (
is_array($array2[$key]))
$merged[$key] = is_array($merged[$key]) ? array_merge_recursive_distinct($merged[$key], $array2[$key]) : $array2[$key];
else
$merged[$key] = $val;

return
$merged;
}
?>
22
walf
13 年前
這裡有很多遞迴的範例,目的是使其行為更像 array_merge(),但它們沒有完全正確,或相當客製化。我認為這個版本最相似,接受超過 2 個參數,並且可以在一個地方重新命名。

<?php

function array_merge_recursive_simple() {

if (
func_num_args() < 2) {
trigger_error(__FUNCTION__ .' 需要兩個或更多陣列參數', E_USER_WARNING);
return;
}
$arrays = func_get_args();
$merged = array();
while (
$arrays) {
$array = array_shift($arrays);
if (!
is_array($array)) {
trigger_error(__FUNCTION__ .' 遇到非陣列參數', E_USER_WARNING);
return;
}
if (!
$array)
continue;
foreach (
$array as $key => $value)
if (
is_string($key))
if (
is_array($value) && array_key_exists($key, $merged) && is_array($merged[$key]))
$merged[$key] = call_user_func(__FUNCTION__, $merged[$key], $value);
else
$merged[$key] = $value;
else
$merged[] = $value;
}
return
$merged;
}

$a1 = array(
88 => 1,
'foo' => 2,
'bar' => array(4),
'x' => 5,
'z' => array(
6,
'm' => 'hi',
),
);
$a2 = array(
99 => 7,
'foo' => array(8),
'bar' => 9,
'y' => 10,
'z' => array(
'm' => 'bye',
11,
),
);
$a3 = array(
'z' => array(
'm' => 'ciao',
),
);
var_dump(array_merge($a1, $a2, $a3));
var_dump(array_merge_recursive_simple($a1, $a2, $a3));
var_dump(array_merge_recursive($a1, $a2, $a3));
?>

結果為

array(7) { array(7) { array(7) {
int(1) int(1) int(1)
["foo"]=> ["foo"]=> ["foo"]=>
array(1) { array(1) { array(2) {
[0]=> [0]=> [0]=>
int(8) int(8) int(2)
} } [1]=>
["bar"]=> ["bar"]=> int(8)
int(9) int(9) }
["x"]=> ["x"]=> ["bar"]=>
int(5) int(5) array(2) {
["z"]=> ["z"]=> [0]=>
array(1) { array(3) { int(4)
["m"]=> [0]=> [1]=>
string(4) "ciao" int(6) int(9)
} ["m"]=> }
[1]=> string(4) "ciao" ["x"]=>
int(7) [1]=> int(5)
["y"]=> int(11) ["z"]=>
int(10) } array(3) {
} [1]=> [0]=>
int(7) int(6)
["y"]=> ["m"]=>
int(10) array(3) {
} [0]=>
string(2) "hi"
[1]=>
string(3) "bye"
[2]=>
string(4) "ciao"
}
[1]=>
int(11)
}
[1]=>
int(7)
["y"]=>
int(10)
}
12
fantomx1 at gmail dot com
8 年前
我稍微改進了 daniel 和 gabriel 的貢獻,使其行為更像原始的 array_merge 函數,以附加數值鍵而不是覆寫它們,並新增了指定要合併哪些元素的有用選項,因為您通常需要僅合併陣列樹的特定部分,而陣列的某些部分只需要讓後面的覆寫先前的即可。透過指定輔助元素 mergeWithParent=true,該陣列部分將被合併,否則後面的陣列部分將覆寫先前的部分。陣列的第一層行為與經典的 array_merge 相同。

function array_merge_recursive_distinct ( array &$array1, array &$array2 )
{
static $level=0;
$merged = [];
if (!empty($array2["mergeWithParent"]) || $level == 0) {
$merged = $array1;
}

foreach ( $array2 as $key => &$value )
{
if (is_numeric($key)) {
$merged [] = $value;
} else {
$merged[$key] = $value;
}

if ( is_array ( $value ) && isset ( $array1 [$key] ) && is_array ( $array1 [$key] )
) {
$level++;
$merged [$key] = array_merge_recursive_distinct($array1 [$key], $value);
$level--;
}
}
unset($merged["mergeWithParent"]);
return $merged;
}
8
thomas at n-o-s-p-a-m dot thoftware dot de
16 年前
這是一個簡單的三行方法。

簡短描述:如果其中一個參數不是陣列,則會回傳第一個參數。如果兩個陣列中都有元素是陣列,則會遞迴合併這些陣列,否則,$ins 中的元素會覆寫 $arr 中的元素(無論鍵是否為數值)。這也適用於 $arr 中的陣列,如果 $ins 中的元素是純量值(與之前的方法不同)。

function array_insert($arr,$ins) {
# 迴圈遍歷 $ins 中的所有元素
if (is_array($arr) && is_array($ins)) foreach ($ins as $k => $v) {
# 鍵存在於 $arr 中,且兩個元素都是陣列:遞迴合併。
if (isset($arr[$k]) && is_array($v) && is_array($arr[$k])) $arr[$k] = array_insert($arr[$k],$v);
# 在這裡放置更多條件(見下方)
# ...
# 否則,將 $arr 中的元素替換為 $ins 中的元素
else $arr[$k] = $v;
}
# 回傳合併後的陣列
return($arr);
}

除了 felix dot ospald at gmx dot de 的說法之外,我認為沒有必要使用型別轉換來比較鍵,因為如果鍵可以是整數,它總是會被轉換為整數。試試看:

$a = array('1'=>'1');
echo gettype(key($a));

它會輸出 'integer'。因此,為了讓整數鍵被附加而不是被替換,請加入這一行:

elseif (is_int($k)) $arr[] = $v;

我使用的一個條件是:

elseif (is_null($v)) unset($arr[$k]);

因此,$ins 中的 NULL 值將會取消 $arr 中對應的元素(這與將其設定為 NULL 不同!)。這可能是對 felix dot ospald at gmx dot de 的另一個補充:檢查鍵是否存在於陣列中的絕對正確方法是使用 array_key_exists() (在目前的上下文中不需要,因為 isset() 與 is_array() 結合使用)。即使元素的值為 NULL,array_key_exists() 也會回傳 TRUE。

最後一個:如果想要將此方法用於兩個以上的陣列,只需使用:

function array_insert_mult($arr) {
# 多於 1 個參數:附加所有參數。
if (func_num_args() > 1) foreach (array_slice(func_get_args(),1) as $ins) $arr = array_insert($arr,$ins);
# 回傳合併後的陣列
return($arr);
}

如果您擔心維護參考:在賦值/使用值作為參數時,只需使用 $ins[$k] 而不是 $v。
4
remy dot damour at -please-no-spam-laposte dot net
15 年前
如果您想要做的是合併陣列中所有本身就是陣列的值,以取得深度為 1 的結果陣列,那麼您更需要的是 array_flatten 函式。

不幸的是,我在 PHP 中沒有找到這樣的原生函式,以下是我寫的一個:

<?php
/**
* 將陣列展平,使結果陣列的深度為 1。
* 如果任何值本身是陣列,它會被父陣列合併,依此類推。
*
* @param array $array
* @param bool $preserver_keys OPTIONAL 當為 true 時,合併巢狀陣列時會保留鍵 (=> 具有相同鍵的值會被覆寫)
* @return array
*/
function array_flatten($array, $preserve_keys = false)
{
if (!
$preserve_keys) {
// 確保鍵是數值,以避免在呼叫 array_merge 時被覆寫
$array = array_values($array);
}

$flattened_array = array();
foreach (
$array as $k => $v) {
if (
is_array($v)) {
$flattened_array = array_merge($flattened_array, call_user_func(__FUNCTION__, $v, $preserve_keys));
} elseif (
$preserve_keys) {
$flattened_array[$k] = $v;
} else {
$flattened_array[] = $v;
}
}
return
$flattened_array;
}

// 範例
$a = array ('k1' => 'a', 'k2' => array('k1' => 'b', 'k4' => array('k3' => 'c')));
var_export(array_flatten($a)); // 輸出:array(0 => 'a', 1 => 'b', 2 => 'c')
var_export(array_flatten($a, true)); // 輸出:array('k1' => 'b', 'k3' => 'c') // 第一個 'k1' 的值被巢狀的 'k1' 的值覆寫
?>
2
jonnybergstrom at googles mail domain dot comm
15 年前
這個函式對我不起作用 - 或者說它沒有像我認為的那樣運作。所以我寫了下面的函式,它會合併兩個陣列,並回傳結果陣列。基礎陣列是左邊的 ($a1),如果鍵在兩個陣列中都設定了,則右邊的值優先。如果左邊的值是陣列,而右邊的值也是陣列,則函式會呼叫自身 (遞迴)。如果左邊的值是陣列,而右邊的值存在但不是陣列,則會使用右邊的非陣列值。

*任何只出現在右邊的鍵都會被忽略*
- 因為在我的實作中我不需要只出現在右邊的值,但如果您需要,您可以進行一些快速修復。

function array_merge_recursive_leftsource(&$a1, &$a2) {
$newArray = array();
foreach ($a1 as $key => $v) {
if (!isset($a2[$key])) {
$newArray[$key] = $v;
continue;
}

if (is_array($v)) {
if (!is_array($a2[$key])) {
$newArray[$key] = $a2[$key];
continue;
}
$newArray[$key] = array_merge_recursive_leftsource($a1[$key], $a2[$key]);
continue;
}

$newArray[$key] = $a2[$key];
}
return $newArray;
}
2
spambegone at cratemedia dot com
16 年前
我嘗試過這些 array_merge_recursive 函式,但沒有太多成功。也許這只是我個人的問題,但它們似乎實際上沒有超過一層的深度?就像所有事情一樣,通常自己寫一個更容易,我就是這麼做的,而且它似乎按照我想要的方式運作。無論如何,我的函式沒有經過廣泛的測試,但它是一個簡單的函式,所以希望這對其他人有用,我分享一下。

此外,PHP 函式 array_merge_recursive() 對於我的目的不起作用,因為它沒有像我需要的那樣覆寫值。您知道它是如何運作的,它只是將其變成一個具有多個值的陣列…如果您的程式碼預期一個字串,這就沒有幫助。

function array_merge_recursive_unique($array1, $array2) {

// 策略
/*
合併 array1 和 array2,在它們重疊的地方用第 2 個陣列的值覆寫第 1 個陣列的值。
使用 array1 作為基礎陣列,然後加入
來自 array2 的值(如果它們存在)。

遍歷 array2 中的每個值,看看 array1 中是否有對應的值。
如果有的話,用第二個陣列的值覆寫。如果是陣列,則遞迴執行此函式並回傳值。如果它是
一個字串,用 array2 中的值覆寫 array1 中的值。
如果 array2 中存在 array1 中找不到的值,則將其加入 array1。

如果 array2 中存在 array1 中找不到的值,則將其加入 array1。
*/

// 迴圈遍歷 $array2
foreach($array2 AS $k => $v) {

// 檢查值是否存在於 $array1 中
if(!empty($array1[$k])) {
// 如果值存在,請檢查它是陣列還是字串
if(!is_array($array2[$k])) {
// 如果是字串,則覆寫
$array1[$k]=$array2[$k];
} else {
// 如果是陣列,則遞迴
$array1[$k] = array_merge_recursive_unique($array1[$k], $array2[$k]);
}
} else {
// 如果值不存在於 $array1 中,則使用 $array2 的值
$array1[$k]=$v;
}
}
unset($k, $v);


return $array1;
}
11
brian at vermonster dot com
20 年前
這是一個相當簡單的函式,它會在遞迴時進行替換。

<?php
/**
* array_merge_recursive2()
*
* 類似於 array_merge_recursive,但鍵值總是會被覆寫。
* 優先權給予第二個陣列。
*
* @static yes
* @public yes
* @param $paArray1 array
* @param $paArray2 array
* @return array
*/
function array_merge_recursive2($paArray1, $paArray2)
{
if (!
is_array($paArray1) or !is_array($paArray2)) { return $paArray2; }
foreach (
$paArray2 AS $sKey2 => $sValue2)
{
$paArray1[$sKey2] = array_merge_recursive2(@$paArray1[$sKey2], $sValue2);
}
return
$paArray1;
}

?>

範例
<?php

$array1
= array(
'liquids' => array(
'water' => array('cold', 'fizzy', 'clean')
,
'beer' => 'warm'
)
);

$array2 = array(
'liquids' => array(
'water' => 'hot'
,'milk' => 'wet'
)
);

$result1 = array_merge_recursive2($array1, $array2);
$result2 = array_merge_recursive2($array2, $array1);
?>

結果 1 是
陣列
(
[liquids] => 陣列
(
[water] => hot
[beer] => warm
[milk] => wet
)
)

結果 2 是
陣列
(
[liquids] => 陣列
(
[water] => 陣列
(
[0] => cold
[1] => fizzy
[2] => clean
)

[milk] => wet
[beer] => warm
)
)
6
mark dot roduner at gmail dot com
14 年前
<?php
/**
* 遞迴地合併任意數量的陣列/參數,將字串鍵的條目替換為後續陣列的值。
* 如果條目或下一個要賦予的值是陣列,則它會自動將兩個參數都視為陣列。
* 數值條目會被附加,而不是被替換,但只有在它們是唯一的情況下才會如此。
*
* 呼叫方式:result = array_merge_recursive_distinct(a1, a2, ... aN)
**/

function array_merge_recursive_distinct () {
$arrays = func_get_args();
$base = array_shift($arrays);
if(!
is_array($base)) $base = empty($base) ? array() : array($base);
foreach(
$arrays as $append) {
if(!
is_array($append)) $append = array($append);
foreach(
$append as $key => $value) {
if(!
array_key_exists($key, $base) and !is_numeric($key)) {
$base[$key] = $append[$key];
continue;
}
if(
is_array($value) or is_array($base[$key])) {
$base[$key] = array_merge_recursive_distinct($base[$key], $append[$key]);
} else if(
is_numeric($key)) {
if(!
in_array($value, $base)) $base[] = $value;
} else {
$base[$key] = $value;
}
}
}
return
$base;
}
?>
11
andyidol at gmail dot com
13 年前
這是我的遞迴合併兩個陣列並覆寫的函式。很適合合併設定。

<?php

function MergeArrays($Arr1, $Arr2)
{
foreach(
$Arr2 as $key => $Value)
{
if(
array_key_exists($key, $Arr1) && is_array($Value))
$Arr1[$key] = MergeArrays($Arr1[$key], $Arr2[$key]);

else
$Arr1[$key] = $Value;

}

return
$Arr1;

}

?>
1
andrew at indigo - sphere dot co dot uk
4 年前
當此函式未產生預期輸出時的替代解決方案:將自訂遞迴函式傳遞給 array_reduce()

例如(使用 PHP 7 的功能來建立遞迴匿名函式)

<?php
function array_merge_recursive(...$arrays): ?array {
return
array_reduce($arrays, new class {
public function
__invoke($carry, $item) {
if (
is_array($carry) && is_array($item) {
return
$this($carry, $item);
}
return
$item ?: $carry;
}
}
}
?>
在這種情況下,truthy 值會覆寫前一個陣列中的值。
當然,這僅作為一個簡單的示例呈現,並非通用的解決方案。
3
robert dot schlak at alcatel-lucent dot com
12 年前
NULL 的存在;這是一個問題和修復的範例。雖然可能不明顯,如果在迴圈中使用 array_merge_recursive 來合併資料庫查詢或其他函式的結果,當資料中存在 NULL 時,您可能會損壞結果。我在從 Oracle DB 遷移到 MySQL DB 時發現了這一點。我必須比對從呼叫 DB 的 PHP 函式傳回的陣列結構,然後就被坑了。array_walk 呼叫為我修復了這個問題。
這是一個簡單的範例,缺少任何 DB 呼叫和迴圈。假設您的陣列具有 DB 資料行名稱(first、last 和 age),並且您需要將資料合併到一個多維陣列中,其中資料行名稱是一個陣列鍵,所有列都位於其下方。損壞發生在 $a3 中。如果使用元素位置 2,則由於元素的摺疊,可能會產生虛構的「pete johnson」。

<?php
print "<pre>Show corruption\\n";
$a1 = array('first'=>'bob', 'last'=>'jones', 'age'=>'48');
$a2 = array('first'=>'sam', 'last'=>'smith', 'age'=>'41');
$a3 = array('first'=>'pete', 'last'=>null, 'age'=>'3');
$a4 = array('first'=>'joe', 'last'=>'johnson', 'age'=>'33');
$a5 = array_merge_recursive($a1,$a2,$a3,$a4);
print_r($a5);

print
"Show Fix\\n";
$a1 = array('first'=>'bob', 'last'=>'jones', 'age'=>'48');
$a2 = array('first'=>'sam', 'last'=>'smith', 'age'=>'41');
$a3 = array('first'=>'pete', 'last'=>null, 'age'=>'3');
array_walk($a3, 'null_to_empty');
$a4 = array('first'=>'joe', 'last'=>'johnson', 'age'=>'33');
$a5 = array_merge_recursive($a1,$a2,$a3,$a4);
print_r($a5);
print
"</pre>\\n";

function
null_to_empty(&$item) {

$item = is_null($item) ? '' : $item;
}
?>
2
miniscalope at gmail dot com
15 年前
我會合併 2 個陣列,但在結果陣列中保持值唯一。
希望這會有所幫助...
<?php

function array_merge_recursive_unique($array1, $array2) {

foreach(
$array2 AS $k => $v) {
if(!isset(
$array1[$k]))
{
$array1[$k] = $v;
}
else
{
if(!
is_array($v)){
if(
is_array($array1[$k]))
{
if(!
in_array($v,$array1[$k]))
{
$array1[$k][] = $v;
}
}
else
{
if(
$array1[$k] != $v)
$array1[$k] = array($array1[$k], $v);
}
}
else
{
$array1[$k] = array_merge_recursive_unique($array1,$array2[$k]);
}

}

}
unset(
$k, $v);
return
$array1;
}

?>
2
paha at paha dot hu
17 年前
在這個版本中,只有當值不是陣列時才會被覆寫。如果值是陣列,其元素將會被合併/覆寫。

// array_merge_recursive 會用下一個值覆蓋值。
// 基於:https://php.dev.org.tw/manual/hu/function.array-merge-recursive.php 2006 年 12 月 9 日 03:38
function array_merge_recursive_unique($array0, $array1)
{
$arrays = func_get_args();
$remains = $arrays;

// 我們遍歷每個陣列,並將值放入結果中(不考慮先前的值)。
// 不考慮先前的值)。
$result = array();

// 循環處理可用的陣列
foreach($arrays as $array) {

// 第一個剩餘的陣列是 $array。我們正在處理它。所以
// 我們將它從剩餘的陣列中移除。
array_shift($remains);

// 我們不關心非陣列參數,就像 PHP 5.0 以來的 array_merge 一樣。
if(is_array($array)) {
// 循環處理值
foreach($array as $key => $value) {
if(is_array($value)) {
// 我們收集所有具有此鍵的剩餘陣列
$args = array();
foreach($remains as $remain) {
if(array_key_exists($key, $remain)) {
array_push($args, $remain[$key]);
}
}

if(count($args) > 2) {
// 進行遞迴
$result[$key] = call_user_func_array(__FUNCTION__, $args);
} else {
foreach($value as $vkey => $vval) {
$result[$key][$vkey] = $vval;
}
}
} else {
// 簡單地放入值
$result[$key] = $value;
}
}
}
}
return $result;
}
3
phil dot kemmeter at gmail dot com
15 年前
我稍微修改了這個版本,使該函數不會覆寫任何值,而是將它們插入到陣列中的可用鍵中

function my_array_merge ($arr,$ins) {
if(is_array($arr))
{
if(is_array($ins)) foreach($ins as $k=>$v)
{
if(isset($arr[$k])&&is_array($v)&&is_array($arr[$k]))
{
$arr[$k] = my_array_merge($arr[$k],$v);
}
else {
// 這是新的迴圈 :)
while (isset($arr[$k]))
$k++;
$arr[$k] = $v;
}
}
}
elseif(!is_array($arr)&&(strlen($arr)==0||$arr==0))
{
$arr=$ins;
}
return($arr);
}

範例

$array1 = array(
100 => array(30),
200 => array(20, 30)
);

$array2 = array(
100 => array(40),
201 => array(60, 30)
);

print_r(my_array_merge($array1,$array2));

使用 array_merge_recursive 的輸出
陣列
(
[0] => 陣列
(
[0] => 30
)

[1] => 陣列
(
[0] => 20
[1] => 30
)

[2] => 陣列
(
[0] => 40
)

)
這不是我期望從 MERGE 常式獲得的結果...

使用目前函數的輸出

陣列
(
[100] => 陣列
(
[0] => 30
[1] => 40
)

[200] => 陣列
(
[0] => 20
[1] => 30
)

)

這是我想要的 :)
0
dev at oove dot blue
2 年前
我正在尋找類似這樣的函數
合併一個或多個陣列,而不附加值,只需覆寫並在需要時擴充陣列。
適用於合併組態或合併要儲存在資料庫中的 json 資料(我的情況)

類似於 javascript 中的 Object.assign

public static function array_merge()
{
// 保存所有傳遞的陣列
$params = func_get_args ();
// 第一個陣列用作基礎,其他所有陣列都會覆寫它
$return = array_shift ( $params );

if(!is_array($return))
$return = [];
// 將所有陣列合併到第一個陣列上
foreach ( $params as $array ) {
foreach ( $array as $key => $value ) {

if(!isset($return[$key]) || !is_array($value)) {
$return[$key] = $value;
}
else
{
$return[$key] = ArrayTools::array_merge( $return[$key], $value );
}
}
}

return $return;

}
0
hailongzh at hotmail dot com
5 年前
分享我的程式碼以保留數字鍵

function revise_keys($source)
{
if (!is_array($source)) {
return $source;
}

$target = [];

foreach ($source as $key => $value) {
$target['S' . $key] = revise_keys($value);
}

return $target;
}

function revert_keys($source)
{
if (!is_array($source)) {
return $source;
}

$target = [];

foreach ($source as $key => $value) {
$target[substr($key, 1 - strlen($key))] = revert_keys($value);
}

return $target;
}

function enhanced_array_merge_recursive(...$candidates)
{
$merged = [];

foreach ($candidates as $candidate) {
if (!is_array($candidate)) {
continue;
}

$merged = array_merge_recursive($merged, revise_keys($candidate));
}

return revert_keys($merged);
}
0
gullevek at gullevek dot org
5 年前
walfs 的版本相當不錯,但它總是假設我們想要數字鍵作為數字鍵。在某些情況下,數字鍵實際上是一個字串 '123'

為此,我修改了該函數,使最後一個參數成為一個真正的開關,以開啟數字鍵。預設情況下,鍵都是字串。

<?php
function array_merge_recursive_simple()
{
// 如果參數不足則中斷 (我們至少需要兩個)
if (func_num_args() < 2) {
trigger_error(__FUNCTION__ .' 需要兩個或多個陣列參數', E_USER_WARNING);
return;
}
// 預設鍵不是字串
$key_is_string = false;
$arrays = func_get_args();
// 如果最後一個不是陣列,則假設它是鍵始終為字串的觸發器
if (!is_array(end($arrays))) {
if (
array_pop($arrays)) {
$key_is_string = true;
}
}
// 檢查陣列計數是否至少為兩個,否則我們沒有足夠的陣列
if (count($arrays) < 2) {
trigger_error(__FUNCTION__.' 需要兩個或多個陣列參數', E_USER_WARNING);
return;
}
$merged = array();
while (
$arrays) {
$array = array_shift($arrays);
if (!
is_array($array)) {
trigger_error(__FUNCTION__ .' 遇到非陣列參數', E_USER_WARNING);
return;
}
if (!
$array) {
continue;
}
foreach (
$array as $key => $value) {
if (
is_string($key) || $key_is_string === false) {
if (
is_array($value) && array_key_exists($key, $merged) && is_array($merged[$key])) {
$merged[$key] = call_user_func(__FUNCTION__, $merged[$key], $value, $key_is_string);
} else {
$merged[$key] = $value;
}
} else {
$merged[] = $value;
}
}
}
return
$merged;
}
?>
1
Anonymous
9 年前
注意。
(使用 PHP 5.4. XAMPP)

具有數字鍵的值總是附加。合併陣列的索引由第一個陣列的起始索引決定。具有數字鍵的 Value4 似乎總是附加的。
如果一個鍵看起來像一個整數,array_merge_recursive 會將該字串解釋為一個數字。

在範例中,$arr['farbe']['22'] = 'grün' 將在 array_merge_recursive 後在 $res['farbe'][33] 中找到。

$ar1 = array("farbe" => array (31 => 'holla', "rot", "favorit" => "gelb2"), "favorit" => "gelb1", 5);
$ar2 = array(10, "farbe" => array ('22' => "grün", "favorit" => 2, "blau"));
$result = array_merge_recursive ($ar1, $ar2);
var_dump($result);
echo('<hr>');

// var_dump
array(4) {
["farbe"]=>
array(5) {
[31]=>
string(5) "holla"
[32]=>
string(3) "rot"
["favorit"]=>
array(2) {
[0]=>
string(5) "gelb2"
[1]=>
int(2)
}
[33]=>
string(5) "grün"
[34]=>
string(4) "blau"
}
["favorit"]=>
string(5) "gelb1"
[0]=>
int(5)
[1]=>
int(10)
}
-1
zubkov dot rabota at gmail dot com
7 年前
這個遞迴陣列合併函式不會重新編號整數鍵,而是將新值附加到現有值,或者如果該鍵值對不存在,則新增一個新的 [鍵 => 值] 對。

function array_merge_recursive_adv(array &$array1, $array2) {
if(!empty($array2) && is_array($array2))
foreach ($array2 as $key => $value) {
if(array_key_exists($key,$array1)) {
if(is_array($value)){
array_merge_recursive_adv($array1[$key], $value);
} else {
if(!empty($array1[$key])) {
if(is_array($array1[$key])){
array_push($array1[$key], $value);
} else {
$array1[$key] = [$array1[$key]];
$array1[$key][] = $value;
}
} else if(empty($array1[$key])) {
$array1[$key] = $value;
}
}
} else {
$array1[$key] = $value;
}
}
return $array1;
}
-2
zubkov dot rabota at gmail dot com
7 年前
這個遞迴陣列合併函式不會重新編號整數鍵,而是將新值附加到現有值,或者如果該鍵值對不存在,則新增一個新的 [鍵 => 值] 對。

function array_merge_recursive_adv(array &$array1, $array2) {
if(!empty($array2) && is_array($array2))
foreach ($array2 as $key => $value) {
if(array_key_exists($key,$array1)) {
if(is_array($value)){
array_merge_recursive_adv($array1[$key], $value);
} else {
if(!empty($array1[$key])) {
if(is_array($array1[$key])){
array_push($array1[$key], $value);
} else {
$array1[$key] = [$array1[$key]];
$array1[$key][] = $value;
}
} else if(empty($array1[$key])) {
$array1[$key] = $value;
}
}
} else {
$array1[$key] = $value;
}
}
return $array1;
}
-1
Anonymous
9 年前
簡單範例

<?php

$Array1
= [1, 2];
$Array2 = [3, 4];

echo
implode("<br>", array_merge_recursive($Array1, $Array2));

?>

輸出
1
2
3
4
0
php at metehanarslan dot com
10 年前
有時候你需要用另一個陣列來修改一個陣列,這裡是我用遞迴方式取代陣列內容的方法,並提供刪除選項。這裡我使用 "::delete::" 作為保留字來刪除項目。

<?php
$person
= array(
"name" => "Metehan",
"surname"=>"Arslan",
"age"=>27,
"mail"=>"hidden",
"favs" => array(
"language"=>"php",
"planet"=>"mercury",
"city"=>"istanbul")
);

$newdata = array(
"age"=>28,
"mail"=>"::delete::",
"favs" => array(
"language"=>"js",
"planet"=>"mercury",
"city"=>"shanghai")
);

print_r(array_overlay($person,$newdata));
// result: Array ( [name] => Metehan [surname] => Arslan [age] => 28 [favs] => Array ( [language] => js [planet] => mercury [city] => shanghai ) )

function array_overlay($a1,$a2)
{
foreach(
$a1 as $k => $v) {
if (
$a2[$k]=="::delete::"){
unset(
$a1[$k]);
continue;
};
if(!
array_key_exists($k,$a2)) continue;
if(
is_array($v) && is_array($a2[$k])){
$a1[$k] = array_overlay($v,$a2[$k]);
}else{
$a1[$k] = $a2[$k];
}

}
return
$a1;
}
?>
0
lsiq at papotam com
14 年前
<?php

// 這個函式將陣列與 $_SESSION 合併
// 如果省略第二個參數,則會合併到根目錄
// 如果給定一個 'path' 陣列,則會進行深度合併

function arr2sess($arr, $path=array()){
if (!
is_array($arr)) return false;
foreach(
$arr as $k => $v){
if(
is_array($arr[$k])) {
$path[] = $k;
arr2sess($arr[$k], $path);
}else{
$ref = &$_SESSION;
if(
$path){
foreach(
$path as $val){
if(!
$ref[$val]) $ref[$val] = array();
$ref = &$ref[$val];
}
}
$ref[$k] = $v;
}
}
}

session_start();
$x = array(k1=>12, k2=>array(kxx=>'forget me', kyy=>'I was allways here')); // $_SESSION 中有這些嗎?
$rpl = array(k2=>array(kxx=>'I am a replaced value',kzz=>'I am a new value'));
arr2sess($x, array('deep','deep','in_session')); // 你可以使用這種方式
arr2sess($x); // 或是這種方式
arr2sess($rpl); // 將部分內容與 $_SESSION 合併

$w = array(120, q=>array(199,100)); // 對於數字鍵也以相同方式運作
arr2sess($w, array('one','two'));
arr2sess($w);

echo
'<pre>';
print_r($_SESSION);

?>
0
drvali at hotmail dot com
15 年前
<?php
/**
* 合併任意維度的任意數量的陣列,後面的鍵會覆蓋前面的鍵,除非鍵是數值的,在這種情況下,重複的值將不會被加入。
*
* 要合併的陣列會作為參數傳遞給此函式。
*
* @access public
* @return array 合併所有陣列後的結果陣列
*/
function array_merge_replace_recursive() {
// 存放所有傳入的陣列
$params = & func_get_args ();

// 第一個陣列作為基準,其他所有陣列覆蓋在其之上
$return = array_shift ( $params );

// 將所有陣列合併到第一個陣列上
foreach ( $params as $array ) {
foreach (
$array as $key => $value ) {
// 數值鍵的值會被加入 (除非已經存在)
if (is_numeric ( $key ) && (! in_array ( $value, $return ))) {
if (
is_array ( $value )) {
$return [] = $this->array_merge_replace_recursive ( $return [$$key], $value );
} else {
$return [] = $value;
}

// 字串鍵的值會被取代
} else {
if (isset (
$return [$key] ) && is_array ( $value ) && is_array ( $return [$key] )) {
$return [$key] = $this->array_merge_replace_recursive ( $return [$$key], $value );
} else {
$return [$key] = $value;
}
}
}
}

return
$return;
}

$a = array (
"a" => 1,
"b" => 2,
'foo',
'bar'
);
$b = array (
"a" => 2,
"c" => 3,
'foo'
);

$c = array_merge_replace_recursive ( $a, $b );
print_r ( $a );
print_r ( $b );
print_r ( $c );
?>

輸出
陣列
(
[a] => 1
[b] => 2
[0] => foo
[1] => bar
)
陣列
(
[a] => 2
[c] => 3
[0] => foo
)
陣列
(
[a] => 2
[b] => 2
[0] => foo
[1] => bar
[c] => 3
)
0
michiel at synetic dot nl
15 年前
這是對先前發布的 array_merge_recursive_distinct 函數(基於 daniel 的版本)的一個小改進。此實作保留了原始的參數輸入,您可以傳遞無限數量的陣列進行合併。

<?php
function &array_merge_recursive_distinct()
{
$aArrays = func_get_args();
$aMerged = $aArrays[0];

for(
$i = 1; $i < count($aArrays); $i++)
{
if (
is_array($aArrays[$i]))
{
foreach (
$aArrays[$i] as $key => $val)
{
if (
is_array($aArrays[$i][$key]))
{
$aMerged[$key] = is_array($aMerged[$key]) ? PR::array_merge_recursive_distinct($aMerged[$key], $aArrays[$i][$key]) : $aArrays[$i][$key];
}
else
{
$aMerged[$key] = $val;
}
}
}
}

return
$aMerged;
}
?>
0
randallgirard at hotmail dot com
18 年前
我寫了以下程式來合併陣列,在我的專案中主要用於設定... 覺得其他人可能會覺得有用。

function array_merge_recursive_keys( $first, $second, $greedy=false) {
$inter = array_intersect_assoc(array_keys($first), array_keys($second)); # 共用的鍵
# 接下來的想法是,從 $second 中剝離並附加到 $first
foreach ( $inter as $key ) {
# 如果兩者都是陣列,則遞迴
if ( is_array($first[$key]) && is_array($second[$key]) ) {
$first[$key] = array_merge_recursive_keys($first[$key], $second[$key]);
}
# 非貪婪陣列合併
else if ( is_array($first[$key] && !$greedy ) ) {
$first[$key][] = $second[$key];
}
else if ( is_array($second[$key]) && !$greedy ) {
$second[$key][] = $first[$key];
$first[$key] = $second[$key];
}
# 覆寫...
else {
$first[$key] = $second[$key];
}
unset($second[$key]);
}
# 將不匹配的鍵合併到第一個陣列
return array_merge($first, $second);
}
0
thiago dot mata at yahoo dot com dot br
18 年前
<?php
function array_merge_recursive_keep_keys( $arrElement1 , $arrElement2 , $intCount = 0 )
{

$arrNew = array();

$arrElement1Keys = array_keys( $arrElement1 );
$arrElement2Keys = array_keys( $arrElement2 );

$arrDifKeys1 = array_diff( $arrElement1Keys, $arrElement2Keys );
$arrDifKeys2 = array_diff( $arrElement2Keys, $arrElement1Keys );
$arrInter = array_intersect( $arrElement1Keys , $arrElement2Keys );

foreach(
$arrDifKeys1 as $strKey1)
{
$arrNew[ $strKey1 ] = $arrElement1[ $strKey1 ];
}
foreach(
$arrDifKeys2 as $strKey2)
{
$arrNew[ $strKey2 ] = $arrElement2[ $strKey2 ];
}
foreach(
$arrInter as $strInterKey )
{
if(
is_array( $arrElement1[ $strInterKey ] ) && is_array( $arrElement2[ $strInterKey ] ) )
{
$intCount++;
$arrNew[ $strInterKey ] = array_merge_recursive_keep_keys( $arrElement1[ $strInterKey ] , $arrElement2[ $strInterKey ] , $intCount );
}
elseif(
is_array( $arrElement1[ $strInterKey ] ) || is_array( $arrElement2[ $strInterKey ] ) )
{
$arrNew[ $strInterKey ][] = $arrElement1[ $strInterKey ];
$arrNew[ $strInterKey ][] = $arrElement2[ $strInterKey ];
}
else
{
$arrNew[ $strInterKey ] = array();
$arrNew[ $strInterKey ][] = $arrElement1[ $strInterKey ];
$arrNew[ $strInterKey ][] = $arrElement2[ $strInterKey ];
}
}
return
$arrNew;
}
?>
0
paska at kios dot sk
20 年前
這個函式模擬根據 variable_order=GPC 來取代 $_REQUEST。
<?
function array_merge_replace($array, $newValues) {
foreach ($newValues as $key => $value ) {
if (is_array($value)) {
if (!isset($array[$key])) {
$array[$key] = array();
}
$array[$key] = array_merge_replace($array[$key], $value);
} else {
$array[$key] = $value;
}
}
return $array;
}

$_REQUEST = array_merge_replace($_REQUEST, $_GET);
$_REQUEST = array_merge_replace($_REQUEST, $_POST);
$_REQUEST = array_merge_replace($_REQUEST, $_COOKIE);
?>

在主要包含檔案的開頭去除反斜線時很有用
<?
if (get_magic_quotes_gpc() == 1) {

function stripMagicSlashes($element) {
if (is_array($element)) {
return array_map("stripMagicSlashes", $element);
} else {
return stripslashes($element);
}
}

function array_merge_replace($array, $newValues) {
foreach ($newValues as $key => $value ) {
if (is_array($value)) {
if (!isset($array[$key])) {
$array[$key] = array();
}
$array[$key] = array_merge_replace($array[$key], $value);
} else {
$array[$key] = $value;
}
}
return $array;
}

$_GET = array_map("stripMagicSlashes", $_GET);
$_POST = array_map("stripMagicSlashes", $_POST);
$_COOKIE = array_map("stripMagicSlashes", $_COOKIE);

$_REQUEST = array_merge_replace($_REQUEST, $_GET);
$_REQUEST = array_merge_replace($_REQUEST, $_POST);
$_REQUEST = array_merge_replace($_REQUEST, $_COOKIE);

}

$GLOBALS['stripped'] = true;
?>

基於此網站用戶提供的範例。
-1
manicdepressive at mindless dot com
20 年前
請注意,在某些情況下,當您在給定的節點上
兩個陣列之間有共同的鍵和值時,
如果該值為 NULL,array_merge_recursive() 的行為會有所不同,
而不是非空值。

也就是說,我預期以下前兩個部分的結果
具有相同的結構,但它們並非如此。
如果這可能適用於您,請自行查看。

<pre><?php

$a1
= array('a'=>'b');
$a2 = array('a'=>'b');
$a3 = array_merge_recursive($a1,$a2);
var_export($a3);
echo
"\n\n";

$a1 = array('a'=>NULL);
$a2 = array('a'=>NULL);
$a3 = array_merge_recursive($a1,$a2);
var_export($a3);
echo
"\n\n";

$a1 = array('a'=>'b');
$a2 = array('a'=>NULL);
$a3 = array_merge_recursive($a1,$a2);
var_export($a3);
echo
"\n\n";

?></pre>

如果該值為空陣列,也會發生這種行為。
事實上,在上面的範例中,將空陣列與
所有 NULL 的出現次數互換將產生相同的結果。

程式碼直到黎明! -mark
-1
felix dot ospald at gmx dot de
16 年前
如果您想要正確且高效能的行為(與其他文章相比),請使用此程式碼。它如上面所述的方式運作。
如果您希望始終保留鍵,並且如果它們是數值的,則不附加或重新編號,請註解掉 "if (((string) $key) === ((string) intval($key)))" 的情況。
@spambegone at cratemedia dot com:使用 empty 不是檢查項目是否在陣列中的正確方法,請使用 isset!

<?php

function array_merge_recursive2($array1, $array2)
{
$arrays = func_get_args();
$narrays = count($arrays);

// 檢查參數
// 如果需要更高的效能,可以註解掉這段 (在這種情況下,如果參數不是陣列,foreach迴圈會觸發警告)
for ($i = 0; $i < $narrays; $i ++) {
if (!
is_array($arrays[$i])) {
// 在這種情況下,array_merge_recursive 也會回傳 null
trigger_error('參數 #' . ($i+1) . ' 不是陣列 - 嘗試合併陣列與純量值!回傳 null!', E_USER_WARNING);
return;
}
}

// 第一個陣列在所有情況下都會輸出
$ret = $arrays[0];

// 將 $ret 與其餘陣列合併
for ($i = 1; $i < $narrays; $i ++) {
foreach (
$arrays[$i] as $key => $value) {
if (((string)
$key) === ((string) intval($key))) { // 整數或字串形式的整數索引 - 附加
$ret[] = $value;
}
else {
// 字串索引 - 合併
if (is_array($value) && isset($ret[$key])) {
// 如果 $ret[$key] 不是陣列,你嘗試將一個純量值與陣列合併 - 結果是未定義的(不相容的陣列)
// 在這種情況下,呼叫會觸發 E_USER_WARNING 並且 $ret[$key] 將會是 null。
$ret[$key] = array_merge_recursive2($ret[$key], $value);
}
else {
$ret[$key] = $value;
}
}
}
}

return
$ret;
}

// 範例:

print_r(array_merge_recursive2(array('A','B','C' => array(1,2,3)), array('D','C' => array(1,4))));
/*
Array
(
[0] => A
[1] => B
[C] => Array
(
[0] => 1
[1] => 2
[2] => 3
[3] => 1
[4] => 4
)
[2] => D
)*/

print_r(array_merge_recursive2(array('A','B','0' => array(1,2,3)), array('D','0' => array(1,array(4)))));
/*
Array
(
[0] => Array
(
[0] => 1
[1] => 2
[2] => 3
)
[1] => B
[2] => Array
(
[0] => 1
[1] => Array
(
[0] => 4
)
)
)*/

print_r(array_merge_recursive2(array('A' => array('A' => 1)), array('A' => array('A' => array(2)))));
/*
Warning: Argument #1 is not an array - trying to merge array with scalar! Returning null! in ... on line ...
*/

var_dump(array_merge_recursive2(array('A' => array('A' => 2)), array('A' => array('A' => null))));
/*
array(1) { ["A"]=> array(1) { ["A"]=> NULL } }
*/

?>
-1
Orhan POLAT
9 年前
遞迴合併陣列在現有鍵值方面存在一些問題,所以我寫了上面的函數來解決。

function merge($array0, $array1) {
// 結果
$merged = array();

foreach (func_get_args() as $array) {
// 檢查傳入的參數是否為陣列
if (is_array($array)) {
foreach ($array as $key => $value) {
// 檢查是否存在具有索引鍵:$key 的陣列
if (isset($merged[$key])) {
// 檢查值是否為陣列
if (is_array($value)) {
// 因此我們必須將目前的值與現有的陣列合併
$merged[$key] = call_user_func_array(__FUNCTION__, $merged[$key], $value);
} else {
if (!is_array($merged[$key])) {
// 如果現有的陣列索引鍵:$key 不是一個陣列
// 我們將其轉換成一個陣列
$merged[$key] = array($merged[$key]);
}

// 然後加入目前的值
$merged[$key][] = $value;
}
} else {
// 如果不存在則建立陣列
$merged[$key] = $value;
}
}
}
}

return $merged;
}
-1
scott dot clark at vizioninteractive dot com
16 年前
需要一些方法將兩個陣列融合在一起,在這裡找到一個函數 (來自 thomas,如下所示),並決定進一步更新它,讓它更聰明一點。

<?php
function my_array_merge ($arr,$ins)
{
if(
is_array($arr))
{
if(
is_array($ins)) foreach($ins as $k=>$v)
{
if(isset(
$arr[$k])&&is_array($v)&&is_array($arr[$k]))
{
$arr[$k] = my_array_merge($arr[$k],$v);
}
else
$arr[$k] = $v;
}
}
elseif(!
is_array($arr)&&(strlen($arr)==0||$arr==0))
{
$arr=$ins;
}
return(
$arr);
}
?>
-2
smilingrasta
18 年前
這個函數傾向於重新索引陣列,這在函數描述中沒有提及。

我剛剛嘗試在一個包含錯誤訊息的三維陣列上執行該函數。
第一個維度包含錯誤的嚴重性 ('warn', 'crit'),第二個維度包含行號 (數值),第三個維度包含錯誤訊息。

<?php
# 陣列輸出:
Array
(
[
warn] => Array // 嚴重性 (關聯式)
(
[
2] => Array // 行號 (數值)
(
[
0] => "類別不存在"
[1] => "製造商不存在"
)
)
)

?>

如果我現在使用 array_merge_recursive() 合併兩個或多個這樣的陣列,行號將不會被保留。相反的,它們都會被重新編號,從 0 開始。

只是認為也許有人想知道這個。 :)
regards, smilingrasta
-3
cezarion at cezarion dot net
10 年前
martyniuk 修改後的 array_merge_recursive 版本,不覆寫數值索引鍵
function array_merge_recursive_new()
{
$arrays = func_get_args();
$base = array_shift($arrays);

foreach ($arrays as $array) {
reset($base); // 重要
while (list($key, $value) = @each($array)) {
if (is_array($value) && @is_array($base[$key])) {
$base[$key] = array_merge_recursive_new($base[$key], $value);
} else {
if(isset($base[$key]) && is_int($key)) {
$key++;
}
$base[$key] = $value;
}
}
}

return $base;
}
-4
karl (dot) hepler (at) gmail (dot) com
8 年前
我遇到了一個相當特殊的情況,array_merge_recursive 幾乎可以做到我想要的,但又不完全是。我瀏覽了所有的評論,沒有找到任何真正對我有幫助的內容。我看到很多提交的函數只是試圖重新建立 array_replace_recursive。這不是那樣。

看看程式碼並試用一下。希望它能幫助到有需要的人!

class Arr
{
/**
* 合併多個陣列。
*
* 這與 array_merge_recursive 類似,但略有不同。
* 主要區別在於它會合併子陣列中類似的索引鍵,
* 而不是簡單地將它們推入輸出陣列中。
*
* @param array ...$array
*
* @return array
*/
public static function merge()
{
/** 初始化輸出陣列 */
$merged = [];

/** 遍歷每個參數 */
foreach (func_get_args() as $array) {
/** 遍歷此陣列的每個索引鍵/值 */
foreach ($array as $key => $value) {
/**
* 如果此索引鍵尚未在 merged 中設定,
* 則需要第一次設定
*/
if (! isset($merged[$key])) {
/**
* 在我們設定它之前,我們必須確保
* 如果值是陣列,則深入探究此值,
* 以便處理其所有子元素。
*/
if (is_array($value)) {
$value = static::merge($value);
}

/**
* 現在我們對此值感到滿意,
* 並且確定如果它是陣列,
* 其所有子元素都已處理過,
* 我們就繼續設定它。
*/
$merged[$key] = $value;

/** 我們可以跳過迴圈的剩餘部分 */
continue;
}

/**
* 我們在這裡是因為我們想要設定一個
* 已經在 merged 中設定的鍵。我們不想
* 覆寫任何東西 - 我們想要將它加入。
* 因此,我們需要確保我們正在處理陣列。
*/
if (! is_array($merged[$key])) {
$merged[$key] = [$merged[$key]];
}

/**
* 在將值推入陣列之前,
* 我們需要檢查它本身是否是陣列。
* 如果是,則需要確保其所有子元素
* 都已處理。我們透過合併所有子元素來實現。
* 這就是它與 array_merge_recursive 不同之處,
* 後者只會將子元素推入陣列的末端。
*/
if (is_array($value)) {
$value = forward_static_call_array([Arr::class, 'merge'], $value);
}

/** 現在我們準備將值推入 merged */
$merged[$key][] = $value;
}
}

/** 返回合併後的陣列 */
return $merged;
}
}
To Top