问题
I have two arrays of arrays that have an id
key, and I'd like to merge the data together based on that array's key and key value. The data would look something like:
$color = [
['id' => 1, 'color' => 'red'],
['id' => 2, 'color' => 'green'],
['id' => 3, 'color' => 'blue'],
];
$size = [
['id' => 1, 'size' => 'SM'],
['id' => 2, 'size' => 'XL'],
['id' => 3, 'size' => 'MD'],
['id' => 4, 'size' => 'LG'],
];
$combined = [
['id' => 1, 'color' => 'red', 'size' => 'SM'],
['id' => 2, 'color' => 'green', 'size' => 'XL'],
['id' => 3, 'color' => 'blue', 'size' => 'MD'],
['id' => 4, 'size' => 'LG'],
];
Is there a particularly efficient function or trick for handling something like this? Or should I just loop through the elements of one array and push the contents to the other?
I'm also using Laravel, and the data is a result of an eloquent query, so I can also utilize the collections if it would make the code cleaner.
回答1:
You can use array_replace_recursive
to merge the arrays in your particular situation.
$color = array(
array('id' => 1, 'color' => 'red'),
array('id' => 2, 'color' => 'green'),
array('id' => 3, 'color' => 'blue'),
);
$size = array(
array('id' => 1, 'size' => 'SM'),
array('id' => 2, 'size' => 'XL'),
array('id' => 3, 'size' => 'MD'),
array('id' => 4, 'size' => 'LG'),
);
$merged = array_replace_recursive($color, $size);
Output:
array(4) {
[0]=>
array(3) {
["id"]=>
int(1)
["color"]=>
string(3) "red"
["size"]=>
string(2) "SM"
}
[1]=>
array(3) {
["id"]=>
int(2)
["color"]=>
string(5) "green"
["size"]=>
string(2) "XL"
}
[2]=>
array(3) {
["id"]=>
int(3)
["color"]=>
string(4) "blue"
["size"]=>
string(2) "MD"
}
[3]=>
array(2) {
["id"]=>
int(4)
["size"]=>
string(2) "LG"
}
}
Note: I used the traditional array layout because my PHP version won't support the new one yet :)
Second option
You can also use array_map
. This will let you add as much arrays as you want with a little tweaking.
$merged = array_map(function ($c, $s) {
return array_merge($c, $s);
}, $color, $size);
var_dump($merged); // See output above
回答2:
Use array_replace_recursive function for easy and fast way
array_replace_recursive($color, $size)
回答3:
Folllow this: array_replace_recursive() is recursive : it will recurse into arrays and apply the same process to the inner value.
$combined = array_replace_recursive($color, $size);
then you can print to see the result as bellow:
print_r($combined);
回答4:
Simple nested loop would solve the purpose.
foreach($size as $key => $value1) {
foreach($color as $value2) {
if($value1['id'] === $value2['id']){
$size[$key]['title'] = $value2['color'];
}
}
}
echo '<pre>';
print_r($size);
Output:
Array
(
[0] => Array
(
[id] => 1
[size] => SM
[title] => red
)
[1] => Array
(
[id] => 2
[size] => XL
[title] => green
)
[2] => Array
(
[id] => 3
[size] => MD
[title] => blue
)
[3] => Array
(
[id] => 4
[size] => LG
)
)
回答5:
Try:
$out = array();
foreach ($size as $key => $value){
if(!isset($color[$key])) { $color[$key] = array(); }
$out[] = array_merge((array)$value,(array)$color[$key]);
}
Output:
Array
(
[0] => Array
(
[id] => 1
[size] => SM
[color] => red
)
[1] => Array
(
[id] => 2
[size] => XL
[color] => green
)
[2] => Array
(
[id] => 3
[size] => MD
[color] => blue
)
[3] => Array
(
[id] => 4
[size] => LG
)
)
回答6:
I'd suggest using laravel's collections, since this question has the laravel tag.
$color = collect(
['id' => 1, 'color' => 'red'],
['id' => 2, 'color' => 'green'],
['id' => 3, 'color' => 'blue']
);
$size = collect(
['id' => 1, 'size' => 'SM'],
['id' => 2, 'size' => 'XL'],
['id' => 3, 'size' => 'MD'],
['id' => 4, 'size' => 'LG']
);
$combined = $color->merge($size);
回答7:
Pure php solution is to use array_replace_recursive like this:
array_replace_recursive(
array_combine(array_column($color, "id"), $color),
array_combine(array_column($size, "id"), $size)
);
You should notice that array_replace_recursive
merge arrays by keys.
So, if you get such data from database:
$color = [
['id' => 1, 'color' => 'red'],
['id' => 2, 'color' => 'red']
];
$size = [
['id' => 2, 'size' => 'SM']
];
array_replace_recursive
will return corrupted merge:
$combined = [
['id' => 2, 'color' => 'red', 'size' => 'SM'],
['id' => 2, 'color' => 'red']
];
The solution is to combine array_replace_recursive
with array_column
and array_combine
for merging arrays by their's id
field:
array_replace_recursive(
array_combine(array_column($color, "id"), $color),
array_combine(array_column($size, "id"), $size)
);
array_combine(array_column($color, "id"), $color)
creates associative array with id
as keys.
So, in your case it will return:
$combined = [
1 => ['id' => 1, 'color' => 'red', 'size' => 'SM'],
2 => ['id' => 2, 'color' => 'green', 'size' => 'XL'],
3 => ['id' => 3, 'color' => 'blue', 'size' => 'MD'],
4 => ['id' => 4, 'size' => 'LG'],
];
回答8:
Better way using loop. First calculate the max array the by count this number run a loop. It will work.
回答9:
array_replace_recursive()
is one appropriate technique, but as you will plainly see from this demonstration, you must not rely on it unless the subarrays have matching id
values at the exact same first level indexes. In other words, the function is not replacing based on corresponding id
values, it is blindly replacing based on the array indexes. Notice how the resulting array data is mangled/ruined.
To fix this, you need to assign temporary associative keys using the id
values. array_column()
to the rescue. With a second parameter of null
and a third parameter of 'id'
, new first level associative keys are assigned to each subarray without altering the subarrays themselves.
Code: (Demo)
$color = [
['id' => 1, 'color' => 'red'],
['id' => 2, 'color' => 'green'],
['id' => 3, 'color' => 'blue'],
];
$size = [
['id' => 3, 'size' => 'MD'],
['id' => 1, 'size' => 'SM'],
['id' => 4, 'size' => 'LG'],
['id' => 2, 'size' => 'XL'],
];
var_export(
array_replace_recursive(
array_column($color, null, 'id'),
array_column($size, null, 'id')
)
);
Output:
array (
1 =>
array (
'id' => 1,
'color' => 'red',
'size' => 'SM',
),
2 =>
array (
'id' => 2,
'color' => 'green',
'size' => 'XL',
),
3 =>
array (
'id' => 3,
'color' => 'blue',
'size' => 'MD',
),
4 =>
array (
'id' => 4,
'size' => 'LG',
),
)
You will notice that the output is no longer indexed, but uses the id
values as keys. If is imperative that the result array is indexed, re-index by calling array_values()
on the result array.
Alternatively, if you insist on using nested loops, you should include a conditional break
in your inner loop to prevent useless iterations, like this..
Code: (Demo)
foreach($color as $subarray1) {
foreach ($size as $subarray2) {
if($subarray1['id'] == $subarray2['id']) {
$result[] = $subarray1 + $subarray2;
break;
}
}
}
来源:https://stackoverflow.com/questions/38396616/merging-arrays-based-on-a-value-of-the-key