Reputation: 1692
I have these three arrays:
Array
(
[1] => [email protected]
[2] => [email protected]
[3] => [email protected]
)
Array
(
[1] =>
[2] => 4234235
[3] =>
)
Array
(
[2] => 1
)
And I want to generate this output:
Array
(
[1] => array(
[0] => [email protected]
)
[2] => array(
[0] => [email protected]
[1] => 4234235
[2] => 1
)
[3] => array(
[0] => [email protected]
)
)
I need some assistance because I already researched array_merge_recursive()
and array_merge()
, but I can't get the correct result.
If I need to use foreach()
what must I do to merge these 3 arrays.
Upvotes: 0
Views: 2267
Reputation: 48051
As you have no doubt discovered, array_merge_recursive()
stubbornly smashes all numeric or "numeric string" keys into a 1-dimensional array. To avoid this behavior, you need to cast each of your arrays' initial keys as strings in a way that will not be assumed to be a number by array_merge_recursive()
.
Additionally you want to filter out all elements that have empty values.
I initially wrote a one-liner that performed the key re-casting then filtered the values, but it is less efficient that way. For your case, you should only use array_filter()
on arrays that may possibly contain empty values.
Input Arrays:
$a=[1=>"[email protected]",2=>"[email protected]",3=>"[email protected]"];
$b=[1=>"",2=>"4234235",3=>""];
$c=[2=>1];
Code:
// remove empty values from all arrays that may have them
$b=array_filter($b,'strlen');
// for all arrays, cast numeric keys to string by prepending with a space
function addK($v){return " $v";}
$a=array_combine(array_map('addK',array_keys($a)),$a);
$b=array_combine(array_map('addK',array_keys($b)),$b);
$c=array_combine(array_map('addK',array_keys($c)),$c);
// merge arrays recursively
$merged=array_merge_recursive($a,$b,$c);
// cast keys back to numeric
$merged=array_combine(array_map('trim',array_keys($merged)),$merged);
// force all top-level elements to be arrays
foreach($merged as $k=>$v){
if(is_string($merged[$k])){$merged[$k]=[$v];}
}
var_export($merged);
Output:
array (
1 => array (
0 => '[email protected]',
),
2 => array (
0 => '[email protected]',
1 => '4234235',
2 => 1,
),
3 => array (
0 => '[email protected]',
),
)
For readers who want to know the difference when array_merge_recursive()
is run with no preparation:
array (
0 => '[email protected]',
1 => '[email protected]',
2 => '[email protected]',
3 => '',
4 => '4234235',
5 => '',
6 => 1,
)
Notice the 1d array and the re-indexed keys? ...totally useless for the OP.
Finally, for anyone who wants to re-cast the keys to all arrays and would like to make my process more DRY, there may be an opportunity to set up a variadic function or similar. I merely didn't bother to pursue the notion because I didn't want to make my answer anymore complex and it is not a terrible amount of Repeating Myself.
Upvotes: 1
Reputation: 771
Wrote a little script:
$a = array
(
1=>"[email protected]",
2=>"[email protected]",
3=>"[email protected]",
);
$b = array
(
2 => 4234235
);
$c = array
(
2 => 1
);
$arrayKeys = array_unique(
array_merge(
array_keys($a),
array_keys($b),
array_keys($c)
)
);
$d = array_combine(
$arrayKeys,
array_fill(
0,
count($arrayKeys),
array()
)
);
foreach($a as $key => $value) {
if(!empty($a[$key])) {
$d[$key][] = $a[$key];
}
if(!empty($b[$key])) {
$d[$key][] = $b[$key];
}
if(!empty($c[$key])) {
$d[$key][] = $c[$key];
}
}
var_dump($d);
Also if you want to you can merge together the arrays using the variable names only
//names of the variables to merge together
$arrayVariableNames = array("a","b","c");
//merging array keys together
$arrayKeys = array();
foreach($arrayVariableNames as $variableName) {
$arrayKeys = array_merge(
$arrayKeys,
array_keys(${$variableName})
);
}
$arrayKeys = array_unique($arrayKeys);
//initialize the result array with empty arrays
$resultArray = array_combine(
$arrayKeys,
array_fill(
0,
count($arrayKeys),
array()
)
);
//loop through all the keys and add the elements from all the arrays
foreach($resultArray as $key => &$value) {
foreach($arrayVariableNames as $variableName) {
if(!empty(${$variableName}[$key])) {
$value[] = ${$variableName}[$key];
}
}
}
Upvotes: 4