phparrayssumgroupingarray-merge

Merging two multidimensional arrays and add column values when a combination of two other columns occurs more than once


I'm trying to write a shopping list app for a website which already has ingredients listed in JSON.

The full code is at the bottom, but just to explain; What I'm aiming to do is to be able to merge the 2 arrays, adding the values from the 'quantity' when the 'name' (and preferably also the 'measure') matches.

e.g. 'Sunflower oil' is listed in both JSON feeds. I want it to output as:

{"name":"Sunflower oil","quantity":110,"measure":"ml"}

but it currently overwrites the JSON and the output is:

{"name":"Sunflower oil","quantity":10,"measure":"ml"},

Here's my code:

<?php
$a = '{"ingredients":[{"name": "Sunflower oil","quantity": 100,"measure": "ml"}]}';
$b = '{"ingredients":[{"name": "Sunflower oil","quantity": 10,"measure": "ml"},{"name": "Fennel seeds","quantity": 1,"measure": "teaspoon"},{"name": "Garlic","quantity": 1,"measure": "clove"}]}';
print_r( json_encode(array_merge(json_decode($a, true),json_decode($b, true))) );
?>

Desired output:

{
    "ingredients": [
        {
            "name": "Sunflower oil",
            "quantity": 110,
            "measure": "ml"
        },
        {
            "name": "Olive oil",
            "quantity": 50,
            "measure": "ml"
        },
        {
            "name": "Fennel seeds",
            "quantity": 1,
            "measure": "teaspoon"
        },
        {
            "name": "Garlic",
            "quantity": 1,
            "measure": "clove"
        }
    ]
}

Solution

  • You can use the following code to get the expected result:

    <?php
    $a = '{"ingredients":[{"name": "Sunflower oil","quantity": 100,"measure": "ml"},{"name": "Olive oil","quantity": 50,"measure": "ml"}]}';
    $b = '{"ingredients":[{"name": "Sunflower oil","quantity": 10,"measure": "ml"},{"name": "Fennel seeds","quantity": 1,"measure": "teaspoon"},{"name": "Garlic","quantity": 1,"measure": "clove"}]}';
    
    $aArr = json_decode($a, true);
    $bArr = json_decode($b, true);
    $sumArr = array("ingredients" => array());
    
    foreach ($aArr['ingredients'] as $valA) {
        foreach ($bArr['ingredients'] as $keyB => $valB) {
            if ($valA['name'] == $valB['name'] && 
                $valA['measure'] == $valB['measure']) {
    
                $valA['quantity'] += $valB['quantity'];
                $sumArr['ingredients'][] = $valA;
    
                unset($bArr['ingredients'][$keyB]);
                continue 2;
            } 
        }
        $sumArr['ingredients'][] = $valA;
    }
    $sumArr['ingredients'] = array_merge($sumArr['ingredients'], $bArr['ingredients']);
    print_r( json_encode( $sumArr ));
    ?>