0

I have a json string

$json = '{
    "id": 1,
    "label": "Beef",
    "sector_page_id": null,
    "value": 0,
    "tree_children": [
        {
            "id": 46,
            "label": "Beef",
            "sector_page_id": null,
            "value": 0,
            "tree_children": [
                {
                    "id": 47,
                    "label": "Beef - UK",
                    "sector_page_id": null,
                    "value": 15,
                    "tree_children": []
                },
                {
                    "id": 48,
                    "label": "Beef - Europe",
                    "sector_page_id": null,
                    "value": 25,
                    "tree_children": []
                },
                {
                    "id": 49,
                    "label": "Beef - Rest of World",
                    "sector_page_id": null,
                    "value": 0,
                    "tree_children": []
                }
            ]
        }]
    }' ;

The sum of each tree_children value will be updated on parent value, So the updated json will be like this :

$json = '{
"id": 1,
"label": "Beef",
"sector_page_id": null,
"value": 40,
"tree_children": [
    {
        "id": 46,
        "label": "Beef",
        "sector_page_id": null,
        "value": 40,
        "tree_children": [
            {
                "id": 47,
                "label": "Beef - UK",
                "sector_page_id": null,
                "value": 15,
                "tree_children": []
            },
            {
                "id": 48,
                "label": "Beef - Europe",
                "sector_page_id": null,
                "value": 25,
                "tree_children": []
            },
            {
                "id": 49,
                "label": "Beef - Rest of World",
                "sector_page_id": null,
                "value": 0,
                "tree_children": []
            }
        ]
    }]
}' ;

Explanation: enter image description here

My progress is not upto the mark but still want to share the snippet Snippet Link

$obj =  json_decode($json, 1);


    
    array_walk_recursive($obj, function(&$item, $key) use($obj){
        $sum = 0;
        
        array_walk_recursive($obj, function($item1, $key1) use (&$sum){
            if($key1 == 'value'){
                $sum += $item1;
            }
        });

        if($key == 'value'){
            if($item == 0){
                $item = $sum;
            }
        }
    });
    
    print_r($obj);
  • Array_walk_recursive only gives you the elements and no information about the level you need. If you want a reusable solution try RecursiveArrayIterator. – jspit Apr 28 '22 at 06:55

3 Answers3

1

You shall use recursive function like below.

$obj =  json_decode($json, 1);

// it is important to pass the obj by reference
function recursive_sum (&$obj) {
    if ( count($obj["tree_children"]) == 0 ) {
        return $obj["value"];
    }
    // don't forget to iterate the child using pass-by-reference &
    foreach ( $obj["tree_children"] as &$_obj )
        $obj["value"] += recursive_sum($_obj);
    return $obj["value"];
}
        
recursive_sum($obj);
print_r($obj);
Chun
  • 407
  • 4
  • 10
  • Nice and clean, Thanks! I have also ended up with another solution, i.e. ```function recursive_sum (&$arr, $sum = 0){ if(isset($arr['tree_children']) && !empty($arr['tree_children'])){ foreach($arr['tree_children'] as &$eachChild){ $sum += $eachChild['value']; $arr['value'] = recursive_sum ($eachChild, $sum); } } return $sum; }``` – Subhra Sekhar Mukhopadhyay Apr 28 '22 at 07:06
  • This answer is missing its educational explanation. – mickmackusa Apr 28 '22 at 10:43
1

Decoding your json as an object is ideal for this task because objects are modifiable by reference by default. In other words, you don't need to explicitly write & before a variable.

There is no need to check the existence or emptiness of the relevant properties while recursing because the accessed properties in the sample data are always present.

Loop the tree_children in each level and add the summed value from recursing its children to its value.

The top level return will provide the grand total sum, but that value is not used by the initial function call because the sum_recursive() call is purely used to modify the object.

Code: (Demo)

$obj = json_decode($json);

function sum_recursive(object $obj): int {
    foreach ($obj->tree_children as $child) {
        $obj->value += sum_recursive($child);
    }
    return $obj->value;
}
   
sum_recursive($obj);
var_export($obj);
mickmackusa
  • 43,625
  • 12
  • 83
  • 136
0

My working snippet

function recursive_sum (&$arr, $sum = 0){
   if(isset($arr['tree_children']) && !empty($arr['tree_children'])){
      foreach($arr['tree_children'] as &$eachChild){
        $sum += $eachChild['value'];
        $arr['value'] = recursive_sum ($eachChild, $sum);
      }
   }
   return $sum;
}