'Add data from second 2d array to first 2d array based on related id columns
I have two arrays $a and $b
$a = [
'0' => [
'name'=>'Apple',
'id' => 1
],
'1' => [
'name'=>'Banana',
'id' => 2
],
'2' => [
'name' => 'orange',
'id' => 3
]
];
AND
$b = [
'0' => [
'price'=> 20,
'a_id' => 2
],
'1' => [
'price'=> 10,
'a_id' => 3
],
'3' => [
'price'=> 30,
'a_id' => 1
]
];
I am trying to create another array with mapping with id(array $a), a_id (array $b), where my output will looks like:
$a = [
'0' => [
'id' => 1
'name'=>'Apple',
'price' => 30
],
'1' => [
'id' => 2
'name'=>'Banana',
'price' => 20
],
'2' => [
'id' => 3
'name' => 'orange',
'price' => 10
]
];
I have tried by array map
$combined = array_map(null,$a,$b);
But this result is not my desire result. How can I map my 1st array with 2nd array related by $a['id'] = $b['a_id']
?
Solution 1:[1]
This should work, also if there's no price for an item in the array $b then the default price 0 will be added.
<?php
$result = [];
$t = array_column($b, 'a_id');
foreach($a as $k => $v) {
$index = array_search($v['id'], $t);
$v['price'] = $index !== FALSE ? $b[$index]['price'] : 0;
$result[] = $v;
}
print_r($result);
?>
Result:
(
[0] => Array
(
[name] => Apple
[id] => 1
[price] => 30
)
[1] => Array
(
[name] => Banana
[id] => 2
[price] => 20
)
[2] => Array
(
[name] => orange
[id] => 3
[price] => 10
)
)
Solution 2:[2]
You can use this code
$result = [];
for($i=0; $i<sizeof($a); $i++){
if(array_key_exists($i,$b)){
$b[$i]['id']=$b[$i]['a_id'];
unset($b[$i]['a_id']);
}
$result[] = array_merge($a[$i], array_key_exists($i,$b)?$b[$i]:array());
}
print_r($result);
Solution 3:[3]
You can do it as follows:
foreach($a as $k => $item)
{
$price = 0;
foreach($b as $priceItem)
{
if($priceItem['a_id'] === $item['id'])
{
$price = $priceItem['price'];
break;
}
}
$a[$k]['price'] = $price;
}
However, this isn't too efficient as every new price and item will exponentially increase the loops required.
If you are able to use the product IDs as the key in your first array, you could do it a lot more efficiently:
// Key $a by product ID
$a = [
1 => [
'name'=>'Apple',
'id' => 1
],
2 => [
'name'=>'Banana',
'id' => 2
],
3 => [
'name' => 'orange',
'id' => 3
]
];
foreach($b as $priceItem)
{
$a[$priceItem['a_id']]['price'] = $priceItem['price'];
}
Solution 4:[4]
Not that this is more efficient, but maybe a bit more flexible, and readable. Its on you!
<?php
$a = [
'0' => ['name'=>'Apple', 'id' => 1],
'1' => ['name'=>'Banana', 'id' => 2],
'2' => ['name' => 'orange', 'id' => 3],
'3' => ['name' => 'extra', 'id' => 4]
];
$b = [
'0' => ['price'=> 20, 'a_id' => 2],
'1' => ['price'=> 10, 'a_id' => 3],
'3' => ['price'=> 30, 'a_id' => 1]
];
$lookup = [];
foreach($b as $k => $v) {
if (array_key_exists($v['a_id'], $lookup)) {
// you have multiple prices... do something, throw an error, log an error, overwrite the value
// what ever you want
} else {
// in case you have multiple array items you want to copy over
// you can later merge the array
// if its only ever going to be prices , you can just take the price instead of the unset
$parent_id = $v['a_id'];
unset($v['a_id']);
$lookup[$parent_id] = $v;
}
}
// in case you have more values that you want push, if nothing exists
$default_values = ['price' => 0];
foreach($a as $k => &$v) {
if (array_key_exists($v['id'], $lookup)) {
$v = array_merge($v, $lookup[$v['id']]);
} else {
$v = array_merge($v, $default_values);
}
}
/* bit less readable
foreach($a as $k => &$v)
$v = array_merge($v, array_key_exists($v['id'], $lookup) ? $lookup[$v['id']] : $default_values);
*/
print_r($a);
result
Array
(
[0] => Array (
[name] => Apple [id] => 1 [price] => 30
)
[1] => Array (
[name] => Banana [id] => 2 [price] => 20
)
[2] => Array (
[name] => orange [id] => 3 [price] => 10
)
[3] => Array (
[name] => extra [id] => 4 [price] => 0
)
)
Solution 5:[5]
Be careful to avoid nested array_search()
calls, this will not be the most efficient approach. This task should be completed with a On on each array; in other words, do not iterate either of the arrays more than once if you want the best possible time complexity.
- Use
array_column()
with anull
2nd parameter to temporarily assignid
values as first level keys -- this will make relating the two arrays very easy and efficient. - My snippet below will use "array destructuring" to unpack the
$b
data and pushprice
elements into the result set. - When the loop is finished, use
array_values()
to re-index the output array (if you wish).
Code: (Demo)
$result = array_column($a, null, 'id');
foreach ($b as ['a_id' => $a_id, 'price' => $result[$a_id]['price']]);
var_export(array_values($result));
It's just that easy/simple.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | |
Solution 2 | Bellash |
Solution 3 | |
Solution 4 | Gauthier |
Solution 5 | mickmackusa |