Merge related row data from an array into another array's rows

122 Views Asked by At

I have two 2d arrays where related row data from one array needs to be merged to the other.

The first one has information about the stock status of that day -- this is stored in a different database.

The second array has the information of the products like name, description and so on.

I wish to merge or combine the second arrays data into the first array based on a specific, shared column of values (product_id).

So far I'm using two foreach loops to combine the two. How can I improve my code?

Sample data (the common key is product_id):

$array_one = [
    [
        'product_id' => 1,
        'product_stock' => '1.2',
        'stock_date' => '2022-02-15'
    ],
    [
        'product_id' => 2,
        'product_stock' => '5',
        'stock_date' => '2022-02-15'
    ],
];
$array_two = [
    [
        'product_id' => 1,
        'product_slug' => 'product_one',
        'product_description' => 'this is the product one'
    ],
    [
        'product_id' => 2,
        'product_slug' => 'product_two',
        'product_description' => 'this is the product two'
    ],
    [
        'product_id' => 3,
        'product_slug' => 'product_three',
        'product_description' => 'this is the product three'
    ],
];

My code:

$new_array = [];

foreach ($array_one as $key => $value) {
    $new_array[ $value['product_id'] ] = $value ;
}
foreach ($array_two as $key => $value) {
    if ( isset( $new_array[ $value['product_id'] ] ) ) {
        $new_array[ $value['product_id'] ]['product_slug'] = $value['product_slug'];
        $new_array[ $value['product_id'] ]['product_description'] = $value['product_description'];
    }
}

Result as expected :

array(2) {
  [1]=>
  array(5) {
    ["product_id"]=>
    int(1)
    ["product_stock"]=>
    string(3) "1.2"
    ["stock_date"]=>
    string(10) "2022-02-15"
    ["product_slug"]=>
    string(11) "product_one"
    ["product_description"]=>
    string(23) "this is the product one"
  }
  [2]=>
  array(5) {
    ["product_id"]=>
    int(2)
    ["product_stock"]=>
    string(1) "5"
    ["stock_date"]=>
    string(10) "2022-02-15"
    ["product_slug"]=>
    string(11) "product_two"
    ["product_description"]=>
    string(23) "this is the product two"
  }
}
3

There are 3 best solutions below

0
On BEST ANSWER

Modify your second array first, so that it uses the product ID as key - that makes the look-up of the item corresponding to the product ID from the first array much easier.

$array_two = array_combine(array_column($array_two, 'product_id'), $array_two);
$new_array = [];
foreach($array_one as $product) {
    $product['product_slug'] = $array_two[$product['product_id']]['product_slug'];
    $product['product_description'] =
         $array_two[$product['product_id']]['product_description'];
    $new_array[$product['product_id']] = $product;
}
0
On

One option you can use the array_map function:

$n_arr = array_map(function ($row) use ($array_two){
    foreach ($array_two as $item){
        if($item['product_id'] == $row['product_id']){
            return $item + $row;
        }
    }
    return false;
},$array_one);
0
On

Because the second array can be safely assumed to contain all possible product_ids, you can convert its data into a lookup array -- an array with associative first level key so that related row data can be swiftly accessed.

Then you merely need to loop over the first array and merge the related second array row to the appropriate first array row. (Demo)

$lookup = array_column($array_two, null, 'product_id');
var_export(
    array_map(
        fn($row) => $row + $lookup[$row['product_id']],
        $array_one
    )
);

The same functional style technique above can be translated to two separate foreach() loops if you prefer language constructs for iteration.