Reputation: 971
I know this is quite easily accomplished with a foreach
, then a while
->list, etc procedure, (I have already accomplished it), however I sense that my code is a bit dirty and it doesn't look like the best solution... I'm looking to use native PHP array functions to do the following:
I have two arrays that look like this:
[
['rank' => '579', 'id' => '1'],
['rank' => '251', 'id' => '2'],
]
and
[
['size' => 'S', 'status' => 'A', 'id' => '1'],
['size' => 'L', 'status' => 'A', 'id' => '2'],
]
And I need merge them to produce:
[
['size' => 'S', 'status' => 'A', 'id' => '1', 'rank' => '579'],
['size' => 'L', 'status' => 'A', 'id' => '2', 'rank' => '251'],
]
Is there a way to be able to merge two arrays with the id
value (or any other) without going into a endless set of foreach
s?
Upvotes: 10
Views: 69504
Reputation: 47874
It is not necessary to use a recursive technique nor multiple loops. Merge the two arrays together, then assign temporary first-level keys in the output array based on the rows' id
value. If the id
is being encountered for the first time, merge the row's data with an empty array; otherwise merge the pre-existing row data from result array. To remove the first-level keys after looping, call array_values()
.
Code: (Demo)
$a = [
['rank' => '579', 'id' => '1'],
['rank' => '251', 'id' => '2'],
];
$b = [
['size' => 'S', 'status' => 'A', 'id' => '1'],
['size' => 'L', 'status' => 'A', 'id' => '2'],
];
$result = [];
foreach (array_merge($a, $b) as $row) {
$result[$row['id']] = $row + ($result[$row['id']] ?? []);
}
var_export(array_values($result));
Not represented by the question's sample data, if the two data sets have columnar data collisions in their respective id
group, then later encountered values will overwrite earlier stored values. Demo To reverse that behavior, you can simply swap the data on either side of the "array union operator". Demo Be warned that array union is suitable in this case because the rows contain non-numeric keys. For other scenarios, it may be more reliable to use array_merge()
or array_replace()
instead of the union operator.
If the relating columns have different names, instead of grouping by $row['id']
, cache the grouping value as a variable and fallback to the alternative column name. ($groupKey = $row['id'] ?? $row['otherId'];
Upvotes: 2
Reputation: 776
function custom_array_merge(&$array1, &$array2) {
$result = Array();
foreach ($array1 as $key_1 => &$value_1) {
// if($value['name'])
foreach ($array2 as $key_1 => $value_2) {
if($value_1['name'] == $value_2['name']) {
$result[] = array_merge($value_1,$value_2);
}
}
}
return $result;
}
// Pass $array1, &$array2 and change the $value_2['name'] // name based on which u want to merge.
Upvotes: 2
Reputation: 53
Have a nice one to merging arrays like another languages. It's because php have auto numbering array elements, and merging will dublicate or replace different elements by keys.
Now, it's changed.
// array_fork
public static function array_fork() {
$args = func_get_args();
$result = array();
foreach ($args as $arr) {
is_array($arr) || exit('[' . __METHOD__ . '] Each item must be an array.');
foreach ($arr as $key => $val) {
if (is_array($val)) {
// recursion
!isset($result[$key]) && $result[$key] = array();
$result[$key] = self::array_fork($result[$key], $arr[$key]);
continue;
}
if (is_numeric($key)) {
if (!in_array($arr[$key], $result))
$result[] = $arr[$key];
} else
$result[$key] = $arr[$key];
}
}
return $result;
}
Upvotes: 2
Reputation: 5611
As Ray noticed in a comment, the accepted answer does not actually answer the question. I was unable to find an answer, so I created the following small utility function:
function array_merge_callback($array1, $array2, $predicate) {
$result = array();
foreach ($array1 as $item1) {
foreach ($array2 as $item2) {
if ($predicate($item1, $item2)) {
$result[] = array_merge($item1, $item2);
}
}
}
return $result;
}
Use it as follows:
array_merge_callback($array1, $array2, function ($item1, $item2) {
return $item1['id'] == $item2['id'];
});
Upvotes: 7
Reputation: 16923
$array = array_merge_recursive($array1, $array2);
or make your own function (it may be faster)
function my_array_merge(&$array1, &$array2) {
$result = Array();
foreach($array1 as $key => &$value) {
$result[$key] = array_merge($value, $array2[$key]);
}
return $result;
}
$array = my_array_merge($array1, array2);
print_r($array);
Upvotes: 16
Reputation: 12867
ok, let's suppost your arrays are called $arr1 and $arr2, you could do this:
<?php
$newarray = Array();
foreach ($arr1 as $element=>$value){
$newarray = array_merge($arr1[$element],$arr2[$element])
}
?>
Upvotes: 1