0

I'm trying to format an array where if it doesn't have the particular id, I'm trying to assign the data as 0. But it's not happening.

The problem here I'm facing is when I tried adding $dataset[$label['id']]['data'][] = 0 if it's empty or not found inside labels object from the main array $array, it's not working.

I have this following array:

$array = '[{
        "id": 26,
        "name": "Tactical",
        "count": 127,
        "labels": {
            "2": {
                "id": 2,
                "risk": "Medium",
                "count": 80
            },
            "1": {
                "id": 1,
                "risk": "Low",
                "count": 39
            },
            "3": {
                "id": 3,
                "risk": "High",
                "count": 8
            }
        }
    },
    {
        "id": 14,
        "name": "Citizen Safety",
        "count": 116,
        "labels": {
            "4": {
                "id": 4,
                "risk": "Extreme",
                "count": 7
            },
            "2": {
                "id": 2,
                "risk": "Medium",
                "count": 103
            },
            "3": {
                "id": 3,
                "risk": "High",
                "count": 6
            }
        }
    },
    {
        "id": 25,
        "name": "Strategic",
        "count": 79,
        "labels": {
            "2": {
                "id": 2,
                "risk": "Medium",
                "count": 40
            },
            "1": {
                "id": 1,
                "risk": "Low",
                "count": 11
            },
            "3": {
                "id": 3,
                "risk": "High",
                "count": 28
            }
        }
    }
]';

Here the snippet of code that I'm trying for

$labels = [];
$dataset = [];
    
foreach ($array as $key => $value) {
    $labels[] = $value['name'];
    foreach ($value['labels'] as $label) {
        if (empty($dataset[$label['id']])) {
            $dataset[$label['id']] = [
                'label' => $label['risk'],
                'backgroundColor' => '#FF9534'
            ];
            $dataset[$label['id']]['data'] = [];
            $dataset[$label['id']]['data'][] = $label['count'];
        } else {
            if (empty($dataset[$label['id']]['data'])) {
                $dataset[$label['id']]['data'][] = 0;
            } else {
                $dataset[$label['id']]['data'][] = $label['count'];
            }
        }
    }
}
    
$dataset = [
    'labels' => $labels,
    'datasets' => $dataset,
];
    
echo json_encode($dataset);
die;

And I'm getting the below output

{
    "labels": [
        "Tactical",
        "Citizen Safety",
        "Strategic"
    ],
    "datasets": {
        "2": {
            "label": "Medium",
            "backgroundColor": "#FF9534",
            "data": [
                80,
                103,
                40
            ]
        },
        "1": {
            "label": "Low",
            "backgroundColor": "#FF9534",
            "data": [
                39,
                11
            ]
        },
        "3": {
            "label": "High",
            "backgroundColor": "#FF9534",
            "data": [
                8,
                6,
                28
            ]
        },
        "4": {
            "label": "Extreme",
            "backgroundColor": "#FF9534",
            "data": [
                7
            ]
        }
    }
}

But the actual output I would like to have is the below one

{
    "labels": [
        "Tactical",
        "Citizen Safety",
        "Strategic"
    ],
    "datasets": {
        "2": {
            "label": "Medium",
            "backgroundColor": "#FF9534",
            "data": [
                80,
                103,
                40
            ]
        },
        "1": {
            "label": "Low",
            "backgroundColor": "#FF9534",
            "data": [
                39,
                0,
                11
            ]
        },
        "3": {
            "label": "High",
            "backgroundColor": "#FF9534",
            "data": [
                8,
                6,
                28
            ]
        },
        "4": {
            "label": "Extreme",
            "backgroundColor": "#FF9534",
            "data": [
                0,
                7,
                0
            ]
        }
    }
}

I mean when I loop through the labels from the $array array objects when any array object doesn't have the label object (like medium, low, high, extreme) I'm trying to assign count as 0 which is not happening in the response. Can someone help me with what am I'm missing here? You can check the execution of code here https://sandbox.onlinephpfunctions.com/code/398b2d1aa892e898a72fb053e981519e3215a053

Please find the below image for the difference in output enter image description here

IGP
  • 14,160
  • 4
  • 26
  • 43
06011991
  • 797
  • 2
  • 13
  • 39
  • I don't see any difference between these outputs. Rather than say "this is what I want" and expect us to play "find the differences" you should describe what you want, and it may help you figure out the problem in the process. – miken32 Jul 01 '21 at 16:34
  • @miken32 Please check the screenshot for clarification, I hope that should give you the idea what I'm trying to do – 06011991 Jul 01 '21 at 16:47
  • @NicoHaase If you see this link https://sandbox.onlinephpfunctions.com/code/398b2d1aa892e898a72fb053e981519e3215a053 you can see a for each loop that's the thing I tried – 06011991 Jul 01 '21 at 16:48
  • Please add all attempts to this question by editing it. Also, share what you've tried to resolve the problem – Nico Haase Jul 01 '21 at 19:25

1 Answers1

1

Lets take the example of the second element in your array which looks like this

'labels' => 
        array (size=3)
          4 => 
            array (size=3)
              'id' => int 4
              'risk' => string 'Extreme' (length=7)
              'count' => int 7
          2 => 
            array (size=3)
              'id' => int 2
              'risk' => string 'Medium' (length=6)
              'count' => int 103
          3 => 
            array (size=3)
              'id' => int 3
              'risk' => string 'High' (length=4)
              'count' => int 6

For this element you want the results array to contain a 0 for the label Low (id is 1). In order to create the result set you are iterating over this array with foreach ($value['labels'] as $label) and assigning values for data with $dataset[$label['id']]['data'][] = $label['count'];

All good until now. However, do note when php is iterating over this array it will have only 3 keys, ie. 4, 2 & 3. For which it is populating the results array properly.

Now we are also expecting it to populate count for id 1 which is not even present in that array and is never encountered in the specific iteration. Hence the variable $label['id'] will never be equal to 1 in the assignment line $dataset[$label['id']]['data'][] = $label['count'];.

You can solve this by inserting the missing elements in each of those arrays with a count of 0.

In order to do that we will need a list of all risk labels with their ids as the key. We can use array_column and array_merge_recursive to do that.

Do note the ... in array_merge_recursive. This is called the splat operator and it is used to unpack the array. You can read more about splat on this questions

$riskArray = array_column($array, 'labels');
$riskArrayFiltered = array_column(array_merge_recursive(...$riskArray), 'risk', 'id');

Once we have a list of all risks all we need to do is loop over the $array, check and add any risk label that is missing.

foreach ($array as $key => $value){
    $labelArray = $value['labels'];
    $missingRiskTypes = array_diff(array_keys($riskArrayFiltered), array_keys($labelArray));
    foreach ($missingRiskTypes as $missingRiskId){
        $array[$key]['labels'][$missingRiskId] =
            ['id' => $missingRiskId, 'risk' => $riskArrayFiltered[$missingRiskId], 'count' => 0];
    }
}

Now you can run your codes on this array to get exactly what you are looking for.

I do suggest you should try to change the structure of your array at the time of creation. There should be an easier and cleaner way to accomplish what you are trying to do.

Here is a working example

endeavour
  • 576
  • 4
  • 15
  • My bad, I never thought it would be easier if I had created the missing label in the initial array instead I was always back of formatting the array in such a way I want it to be. Thanks a million for the help :) – 06011991 Jul 02 '21 at 04:53