Reputation: 5069
I have this code
$a1 = array(
'success' => TRUE,
'data' => array(
'foo' =>
array(
21 =>
array(
1 =>
array(1, 2, 3, 4, 5)
)
)
)
);
$a2 = array(
'success' => TRUE,
'data' => array(
'foo' =>
array(
21 =>
array(
7 =>
array(6, 7, 8, 9, 10)
)
)
)
);
$results = array();
$results = array_merge_recursive($results, $a1['data']);
$results = array_merge_recursive($results, $a2['data']);
var_dump($results);
From what I understood of array_merge_recursive(), I am expecting the results would be
array
'foo' =>
array
21 =>
array
1 =>
array
0 => int 1
1 => int 2
2 => int 3
3 => int 4
4 => int 5
7 =>
0 => int 6
1 => int 7
2 => int 8
3 => int 9
4 => int 10
Instead I get this
array
'foo' =>
array
21 =>
array
1 =>
array
0 => int 1
1 => int 2
2 => int 3
3 => int 4
4 => int 5
22 =>
array
7 =>
array
0 => int 6
1 => int 7
2 => int 8
3 => int 9
4 => int 10
Where did the 22
index come from? Why is it outputting differently? Did I use the function wrong?
Upvotes: 3
Views: 351
Reputation: 1525
I just came across the same issue, I wanted to merge the arrays but surprisingly found the keys were changed automatically in the result. The reason was because my "keys" are string of decimal numbers, without any alphabetic characters.
But luckily I noticed that if the keys have alphabetic characters, they could be reserved. So just came up with the following idea, which would append a letter 'S' to each key recursively before the merge, and later remove it in the final result.
Please refer to the enhanced_array_merge_recursive
function for details:
<?php
$aa = [
'10' => 'book',
'14' => ['cat'],
];
$ab = [
'12' => 'cd',
'18' => 'cup',
'14' => ['dog'],
];
var_dump(enhanced_array_merge_recursive($aa, $ab));
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);
}
Output looks like following:
array(4) {
[10] =>
string(4) "book"
[14] =>
array(1) {
[0] =>
array(2) {
[0] =>
string(3) "cat"
[1] =>
string(3) "dog"
}
}
[12] =>
string(2) "cd"
[18] =>
string(3) "cup"
}
Upvotes: 0
Reputation: 13535
array_merge_recursive
merges elements/arrays from the same depth as the first array, but if both arrays the key is a numerical index and they are the same it then appends to it. This is what is happening in your situation. since then your array is appended at 2nd level where index 21
is found by creating index 22
. To receive the desired output you have change your index 21
to a string key like "x21"
Notes from php manual
If the input arrays have the same string keys, then the values for these keys are merged together into an array, and this is done recursively, so that if one of the values is an array itself, the function will merge it with a corresponding entry in another array too. If, however, the arrays have the same numeric key, the later value will not overwrite the original value, but will be appended.
Upvotes: 4