-
-
Save ptz0n/1646171 to your computer and use it in GitHub Desktop.
<?php | |
/** | |
* Merge two dimensional arrays my way | |
* | |
* Will merge keys even if they are of type int | |
* | |
* @param array $array1 Initial array to merge. | |
* @param array ... Variable list of arrays to recursively merge. | |
* | |
* @author Erik Pettersson <[email protected]> | |
*/ | |
function array_merge_myway() | |
{ | |
$output = array(); | |
foreach(func_get_args() as $array) { | |
foreach($array as $key => $value) { | |
$output[$key] = isset($output[$key]) ? | |
array_merge($output[$key], $value) : $value; | |
} | |
} | |
return $output; | |
} | |
/** | |
* Version of array_merge_recursive without overwriting numeric keys | |
* | |
* @param array $array1 Initial array to merge. | |
* @param array ... Variable list of arrays to recursively merge. | |
* | |
* @link http://www.php.net/manual/en/function.array-merge-recursive.php#106985 | |
* @author Martyniuk Vasyl <[email protected]> | |
*/ | |
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 { | |
$base[$key] = $value; | |
} | |
} | |
} | |
return $base; | |
} | |
/** | |
* Marge arrays recursively and distinct | |
* | |
* Merges any number of arrays / parameters recursively, replacing | |
* entries with string keys with values from latter arrays. | |
* If the entry or the next value to be assigned is an array, then it | |
* automagically treats both arguments as an array. | |
* Numeric entries are appended, not replaced, but only if they are | |
* unique | |
* | |
* @param array $array1 Initial array to merge. | |
* @param array ... Variable list of arrays to recursively merge. | |
* | |
* @link http://www.php.net/manual/en/function.array-merge-recursive.php#96201 | |
* @author Mark Roduner <[email protected]> | |
*/ | |
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; | |
} | |
$first = array( | |
1327006800 => array('avgresponse' => 1803), | |
1327003200 => array('avgresponse' => 1453) | |
); | |
$second = array( | |
1327006800 => array('pageviews' => 123), | |
1327003200 => array('pageviews' => 345) | |
); | |
/** | |
* Test functions | |
* | |
*/ | |
echo '<pre>'; | |
// Recursive array merge will not work as expected | |
echo 'array_merge_recursive fails: '; | |
print_r(array_merge_recursive($first, $second)); | |
// Let's try our function out | |
echo "\n", 'array_merge_myway success: '; | |
print_r(array_merge_myway($first, $second)); | |
// Let's try another one | |
echo "\n", 'array_merge_recursive_new works too: '; | |
print_r(array_merge_recursive_new($first, $second)); | |
// Let's try another one | |
echo "\n", 'array_merge_recursive_distinct also works: '; | |
print_r(array_merge_recursive_distinct($first, $second)); |
Thanks.
I use array_merge_recursive_distinct
But I modified the line
if(is_array($value) or is_array($base[$key])) {
into:
if(is_array($value) or (array_key_exists($key, $base) and is_array($base[$key]))) {
As the original version thows an exception when the key does not exists yet...
Perfect!!! Thank you very much!
Excellent! Thank for your this!
Thank you very much, I couldn't figure this one on my own.
However after heavy usage I definitely recommend everyone to test the array_key_exists() against the bool data type with === (or !==) operator, rather than counting on !array_key_exists() - because when the searched key index is 0, then it also evaluates to false which can cause trouble.
Great solution. But I need help for a small change to support the follow array-merge:
{"A":{"test":[]}}
+
{"A":{"test":["test1"]}}
+
{"A":{"test":["test2"]}}
=> for this result:
{"A":
{"test":{
"0":["test1"],
"1":["test2"]
}
}
}
Can you help me? Its the same as your rekursiv merge function, but with your solution the ["test1"] will overrided by ["test2"], because he don't increment the key.
If this function is required targeting PHP v8 (the each command is deprecated) you could do it this way:
function array_merge_recursive_new() {
$arrays = func_get_args();
$base = array_shift($arrays);
foreach ($arrays as $array) {
foreach (array_keys($array) as $i => $key) {
$value = array_values($array)[$i];
$base[$key] = is_array($value) && is_array($base[$key]) ? array_merge_recursive_new($base[$key], $value) : $value;
}
}
return $base;
}
Thank you so much, I was struggling with integer keys
Output: