Home > other >  PHP change a function from from loops to recursion
PHP change a function from from loops to recursion

Time:02-10

I have the following JSON object:

{
    "id": 1,
    "name": null,
    "block": {
        "type": "none",
        "descends": [
            {
                "operation":"sum",
                "descends":[
                    {
                        "label":2,
                        "value":false
                    }
                ]
            },
            {
                "label": 1,
                "value": 3,
            },
            {
                "label": 2,
                "value": 2
            }
        ],
        "label": 1,
        "value": true
    }
}

I want to collect all the label and value attributes and store them in an array, so I created the following function:

public function collectValues($arr){
    $finalValues = [];
    foreach($arr as $key => $element){
        if($key=='block'){
            foreach($element as $key2 => $block){
                if($key2=='descends'){
                    foreach($block as $key3 => $node_block){
                        if($key3=='descends'){
                            foreach($node_block as $key4 => $anotherNode){
                                
                                if($key4 == 'descends'){
                                    foreach($anotherNode as $finalNode){
                                        $finalValues [] = array('lable'=>$finalNode->label, 'value' =>$finalNode->value);
                                    }

                                }
                            }
                            
                        }
                        else{
                            $finalValues [] = array('lable' => $node_block->label, 'value' => $node_block->value);
                        }
                    }
                }
            }

            $finalValues [] = array('lable'=> $element->label, 'value' => $element->value);
        }
    }

    return $finalValues;
}

The function works and I get the following:

[
    {
        "lable": 2,
        "value": false
    },
    {
        "lable": 1,
        "value": 3
    },
    {
        "lable": 2,
        "value": 2
    },
    {
        "lable": 1,
        "value": true
    }
]

The problem is that the JSON object can contain more descends like:

{
    "id": 1,
    "name": null,
    "block": {
        "type": "none",
        "descends": [
            {
                "operation":"sum",
                "descends":[
                    {
                        "operation":"sum",
                        "descends":[
                            {
                                "label":2,
                                "value":false
                            }
                        ],
                        "label":2,
                        "value":false
                    }
                ]
            },
            {
                "operation":"sum",
                "descends":[
                    {
                        "label":2,
                        "value":false
                    }
                ],
                "label": 1,
                "value": 3,
            },
            {
                "label": 2,
                "value": 2
            }
        ],
        "label": 1,
        "value": true
    }
}

This means I will have to add more foreach loops. A good way to handle such a situation is by using recursive. How can I transform the function above into a recursive one?

CodePudding user response:

Your looped function does not make sense to change. Easier to rewrite from scratch Here is my use case for recursion. Maybe there is an easier option, but I didn’t chase optimization

$array = json_decode($json, true); //in $json your JSON)
$result = []; // array for result
checkLabel($array, $result);
print_r($result);

function checkLabel(array $array, &$result){ 
    //first check every element on nested array
    foreach ($array as $key => $value){

        if (is_array($value)) {
            //if found call recursive function
            checkLabel($value, $result);
        }
    }
    //then check 'label' key.. its mean we have attribute
    if (array_key_exists('label', $array)) {
        //save it
        $result[] = [
            'label' => $array['label'],
            'value' => $array['value']??'' //if have label but without value)
        ];
    }
}
  •  Tags:  
  • Related