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)
];
}
}